package guda.house.biz.impl;

import guda.grape.autogen.common.page.BizResult;
import guda.house.biz.BillStatBiz;
import guda.house.biz.beans.vo.*;
import guda.house.biz.enums.*;
import guda.house.biz.form.stat.StatFeeForm;
import guda.house.biz.query.*;
import guda.house.biz.util.Transform;
import guda.house.biz.util.TransformHelper;
import guda.house.dal.dao.*;
import guda.house.dal.dataobject.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by well on 15/11/28.
 */
public class BillStatBizImpl implements BillStatBiz {

    @Autowired
    private BillElecDAO billElecDAO;
    @Autowired
    private BillEstateDAO billEstateDAO;
    @Autowired
    private BillWaterDAO billWaterDAO;
    @Autowired
    private BillParkingDAO billParkingDAO;
    @Autowired
    private BillExtDAO billExtDAO;
    @Autowired
    private SuiteDAO suiteDAO;
    @Autowired
    private UnitDAO unitDAO;
    @Autowired
    private BuildingDAO buildingDAO;
    @Autowired
    private SysVarDAO sysVarDAO;
    @Autowired
    private ParkingDAO parkingDAO;
    @Autowired
    private BillPayDAO billPayDAO;
    @Autowired
    private ExtraFeeDAO extraFeeDAO;
    @Autowired
    private AccountEstateDAO accountEstateDAO;
    @Autowired
    private OfficeEmployeeDAO officeEmployeeDAO;
    @Autowired
    private VillageDAO villageDAO;


    @Override
    public BizResult stat(StatFeeForm statFeeForm) {
        BizResult bizResult = new BizResult();

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd");
        Date startDate = null;
        Date endDate = null;
        try {
            startDate = simpleDateFormat.parse(statFeeForm.getStartDate());
            simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd");
            endDate = simpleDateFormat.parse(statFeeForm.getEndDate());
            if (startDate.after(endDate)) {
                Date temp = startDate;
                startDate = endDate;
                endDate = temp;
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(startDate);
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(endDate);

        int startDay = startCalendar.get(Calendar.DAY_OF_YEAR);
        int endDay = endCalendar.get(Calendar.DAY_OF_YEAR) + 1;

        //List<Long> suiteIdList = getSuiteIdList(statFeeForm);
        BuildingQuery buildingQuery = new BuildingQuery();
        buildingQuery.setPageSize(10000);
        buildingQuery.setVillageId(statFeeForm.getVillageId());
        List<BuildingDO> buildingDOs = buildingDAO.selectForPage(buildingQuery);
        List<Long> buildingIdList = TransformHelper.transform(buildingDOs, new Transform<BuildingDO, Long>() {
            @Override
            public Long transform(BuildingDO object) {
                return object.getBuildingId();
            }
        });
        if (buildingIdList.size() == 0) {
            return null;
        }

        UnitQuery unitQuery = new UnitQuery();
        unitQuery.setPageSize(10000);
        unitQuery.setBuildingIdList(buildingIdList);
        List<UnitDO> unitDOs = unitDAO.selectForPage(unitQuery);
        List<Long> unitIdList = TransformHelper.transform(unitDOs, new Transform<UnitDO, Long>() {
            @Override
            public Long transform(UnitDO object) {
                return object.getUnitId();
            }
        });
        if (unitIdList.size() == 0) {
            return null;
        }

        SuiteQuery suiteQuery = new SuiteQuery();
        suiteQuery.setPageSize(10000);
        suiteQuery.setUnitIdList(unitIdList);
        List<SuiteDO> suiteDOs = suiteDAO.selectForPage(suiteQuery);
        List<Long> suiteIdList = TransformHelper.transform(suiteDOs, new Transform<SuiteDO, Long>() {
            @Override
            public Long transform(SuiteDO object) {
                return object.getSuiteId();
            }
        });
        List<Long> waterMeterSuiteIdList = new ArrayList<Long>();
        List<Long> waterIcSuiteIdList = new ArrayList<Long>();
        List<Long> elecMeterSuiteIdList = new ArrayList<Long>();
        List<Long> elecIcSuiteIdList = new ArrayList<Long>();
        for (SuiteDO suiteDO : suiteDOs) {
            if (suiteDO.getTypeWater().equals(MeterTypeEnum.meter.getDesc())) {
                waterMeterSuiteIdList.add(suiteDO.getSuiteId());
            } else {
                waterIcSuiteIdList.add(suiteDO.getSuiteId());
            }
            if (suiteDO.getTypeElectrical().equals(MeterTypeEnum.meter.getDesc())) {
                elecMeterSuiteIdList.add(suiteDO.getSuiteId());
            } else {
                elecIcSuiteIdList.add(suiteDO.getSuiteId());
            }
        }

        ParkingQuery parkingQuery = new ParkingQuery();
        parkingQuery.setVillageId(statFeeForm.getVillageId());
        parkingQuery.setPageSize(10000);
        List<ParkingDO> parkingDOs = parkingDAO.selectForPage(parkingQuery);
        List<Long> parkingIdList = TransformHelper.transform(parkingDOs, new Transform<ParkingDO, Long>() {
            @Override
            public Long transform(ParkingDO object) {
                return object.getParkingId();
            }
        });

        SysVarQuery sysVarQuery = new SysVarQuery();
        sysVarQuery.setVillageId(statFeeForm.getVillageId());
        sysVarQuery.setVarType(SysVarTypeEnum.deposit.name());
        sysVarQuery.setPageSize(500);
        List<SysVarDO> depositSysVarDOs = sysVarDAO.selectForPage(sysVarQuery);
        Set<Long> depositVarIdSet = TransformHelper.transform2Set(depositSysVarDOs, new Transform<SysVarDO, Long>() {
            @Override
            public Long transform(SysVarDO object) {
                return object.getVarId();
            }
        });

        sysVarQuery.setVarType(SysVarTypeEnum.ext.name());
        sysVarQuery.setPageSize(500);
        List<SysVarDO> extSysVarDOs = sysVarDAO.selectForPage(sysVarQuery);
//        Set<Long> extVarIdSet = TransformHelper.transform2Set(extSysVarDOs, new Transform<SysVarDO, Long>() {
//            @Override
//            public Long transform(SysVarDO object) {
//                return object.getVarId();
//            }
//        });
        //临时费用
        sysVarQuery.setVarType(SysVarTypeEnum.extra_fee.name());
        List<SysVarDO> extraSysVarDOs = sysVarDAO.selectForPage(sysVarQuery);
        bizResult.data.put("extraList", extraSysVarDOs);
        Map<String, List<Long>> extVarMap = new HashMap<String, List<Long>>();
        for (SysVarDO sysVarDO : extSysVarDOs) {
            List<Long> longs = extVarMap.get(sysVarDO.getVarValue());
            if (longs == null) {
                longs = new ArrayList<Long>();
                longs.add(sysVarDO.getVarId());
                extVarMap.put(sysVarDO.getVarValue(), longs);
            } else {
                longs.add(sysVarDO.getVarId());
            }
        }
        List<Long> depositVarIdList = new ArrayList<Long>(depositVarIdSet);
        // List<Long> extVarIdList = new ArrayList<Long>(extVarIdSet);
        Map<String, BillStatVO> map = new LinkedHashMap<String, BillStatVO>();
        for (int i = 0, len = endDay - startDay; i < len; ++i) {
            startCalendar.set(Calendar.DAY_OF_YEAR, startDay + i);
            Date stat = startCalendar.getTime();
            SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-mm-dd");
            BillStatVO billStatVO = statBillByDay(stat, suiteIdList, parkingIdList, depositVarIdList, waterMeterSuiteIdList, waterIcSuiteIdList,
                    elecMeterSuiteIdList, elecIcSuiteIdList,
                    extVarMap, extraSysVarDOs);
            map.put(simpleDateFormat1.format(stat), billStatVO);
        }
        bizResult.data.put("statMap", map);
        bizResult.data.put("extList", new ArrayList(extVarMap.keySet()));

        //统计年度费用
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        long last=0;
        long thisYear = 0;
        long next = 0;
        Long billEstateByYear = billEstateDAO.statBillRate(suiteIdList, year, null);
        if(billEstateByYear!=null){
            thisYear+=billEstateByYear;
        }
        Long billEstateByLastYear = billEstateDAO.statBillRate(suiteIdList, year - 1, null);
        if(billEstateByLastYear!=null){
            last+=billEstateByLastYear;
        }
        Long billEstateByNextYear = billEstateDAO.statBillRate(suiteIdList, year + 1, null);
        if(billEstateByNextYear!=null){
            next+=billEstateByNextYear;
        }
        Long billWaterByYear = billWaterDAO.statBillByYear(suiteIdList, year, null);
        if(billWaterByYear!=null){
            thisYear+=billWaterByYear;
        }
        Long billWaterByLastYear = billWaterDAO.statBillByYear(suiteIdList, year - 1, null);
        if(billWaterByLastYear!=null){
            last+=billWaterByLastYear;
        }
        Long billWaterByNextYear = billWaterDAO.statBillByYear(suiteIdList, year + 1, null);
        if(billWaterByNextYear!=null){
            next+=billWaterByNextYear;
        }
        Long billElecByYear = billElecDAO.statBillByYear(suiteIdList, year, null);
        if(billElecByYear!=null){
            thisYear+=billElecByYear;
        }
        Long billElecByLastYear = billElecDAO.statBillByYear(suiteIdList, year - 1, null);
        if(billElecByLastYear!=null){
            last+=billElecByLastYear;
        }
        Long billElecByNextYear = billElecDAO.statBillByYear(suiteIdList, year + 1, null);
        if(billElecByNextYear!=null){
            next+=billElecByNextYear;
        }
        //其他费用

        Long billExt = billExtDAO.statBillByTime(suiteIdList,getYearFirst(year),getYearLast(year));
        if(billExt!=null){
            thisYear+=billExt;
        }
        Long billExtLast = billExtDAO.statBillByTime(suiteIdList,getYearFirst(year-1),getYearLast(year-1));
        if(billExtLast!=null){
            last+=billExtLast;
        }
        Long billExtNext = billExtDAO.statBillByTime(suiteIdList,getYearFirst(year+1),getYearLast(year+1));
        if(billExtNext!=null){
            next+=billExtNext;
        }
        List<StatObj> totalStat = new ArrayList<StatObj>();
        StatObj lastStat = new StatObj();
        lastStat.setName(String.valueOf(year - 1) + "年");
        lastStat.setFeeTotal(last);
        totalStat.add(lastStat);

        StatObj thisStat = new StatObj();
        thisStat.setName(String.valueOf(year) + "年");
        thisStat.setFeeTotal(thisYear);
        totalStat.add(thisStat);

        StatObj  nextStat = new StatObj();
        nextStat.setName(String.valueOf(year+1)+"年");
        nextStat.setFeeTotal(next);
        totalStat.add(nextStat);

        bizResult.data.put("totalStat",totalStat);

        bizResult.success = true;
        return bizResult;
    }


    public static Date getYearFirst(int year){
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        Date currYearFirst = calendar.getTime();
        return currYearFirst;
    }


    public static Date getYearLast(int year){
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        Date currYearLast = calendar.getTime();

        return currYearLast;
    }

    @Override
    public BizResult statElec(StatFeeForm statFeeForm) {
        BizResult bizResult = new BizResult();
        List<Long> suiteIdList = getSuiteIdList(statFeeForm);
        BillRateVO billRateVO = new BillRateVO();
        if (suiteIdList == null || suiteIdList.size() == 0) {
            bizResult.success = true;
            return bizResult;
        }
        if (!StringUtils.hasText(statFeeForm.getStartDate())) {
            bizResult.success = true;
            return bizResult;
        }
        if (!StringUtils.hasText(statFeeForm.getEndDate())) {
            bizResult.success = true;
            return bizResult;
        }
        String startDate = statFeeForm.getStartDate() + " 00:00:00";
        String endDate = statFeeForm.getEndDate() + " 23:59:59";
        Long elecPayTotal = billElecDAO.statBillRate(suiteIdList, startDate, endDate, null);
        Long elecPayed = billElecDAO.statBillRate(suiteIdList, startDate, endDate, 1);
        billRateVO.setTotal(elecPayTotal);
        billRateVO.setPayed(elecPayed);
        if (elecPayed == null) {
            billRateVO.setPayed(0L);
        }
        if (elecPayTotal == null) {
            billRateVO.setTotal(0L);
        }
        billRateVO.setRate(getRate(elecPayed, elecPayTotal));
        bizResult.data.put("billRateVO", billRateVO);
        bizResult.success = true;
        return bizResult;
    }

    @Override
    public BizResult statWater(StatFeeForm statFeeForm) {
        BizResult bizResult = new BizResult();
        List<Long> suiteIdList = getSuiteIdList(statFeeForm);
        BillRateVO billRateVO = new BillRateVO();
        if (suiteIdList == null || suiteIdList.size() == 0) {
            return bizResult;
        }

        if (!StringUtils.hasText(statFeeForm.getStartDate())) {
            bizResult.success = true;
            return bizResult;
        }
        if (!StringUtils.hasText(statFeeForm.getEndDate())) {
            bizResult.success = true;
            return bizResult;
        }
        String startDate = statFeeForm.getStartDate() + " 00:00:00";
        String endDate = statFeeForm.getEndDate() + " 23:59:59";
        Long waterPayTotal = billWaterDAO.statBillRate(suiteIdList, startDate, endDate, null);
        Long waterPayed = billWaterDAO.statBillRate(suiteIdList, startDate, endDate, 1);
        billRateVO.setTotal(waterPayTotal);
        billRateVO.setPayed(waterPayed);
        billRateVO.setRate(getRate(waterPayed, waterPayTotal));
        if (waterPayed == null) {
            billRateVO.setPayed(0L);
        }
        if (waterPayTotal == null) {
            billRateVO.setTotal(0L);
        }
        bizResult.data.put("billRateVO", billRateVO);
        bizResult.success = true;
        return bizResult;
    }

    @Override
    public BizResult statParking(StatFeeForm statFeeForm) {
        BizResult bizResult = new BizResult();
        ParkingQuery parkingQuery = new ParkingQuery();
        parkingQuery.setVillageId(statFeeForm.getVillageId());
        parkingQuery.setPageSize(10000);
        List<ParkingDO> parkingDOs = parkingDAO.selectForPage(parkingQuery);
        List<Long> parkingIdList = TransformHelper.transform(parkingDOs, new Transform<ParkingDO, Long>() {
            @Override
            public Long transform(ParkingDO object) {
                return object.getParkingId();
            }
        });
        BillRateVO billRateVO = new BillRateVO();
        if (parkingIdList == null || parkingIdList.size() == 0) {
            bizResult.success = true;
            return bizResult;
        }
        if (statFeeForm.getYear() == null) {
            bizResult.success = true;
            return bizResult;
        }

        Long parkingPayTotal = billParkingDAO.statBillRate(parkingIdList, statFeeForm.getYear(), null);
        Long parkingPayed = billParkingDAO.statBillRate(parkingIdList, statFeeForm.getYear(), 1);
        billRateVO.setTotal(parkingPayTotal);
        billRateVO.setPayed(parkingPayed);
        billRateVO.setRate(getRate(parkingPayed, parkingPayTotal));
        if (parkingPayed == null) {
            billRateVO.setPayed(0L);
        }
        if (parkingPayTotal == null) {
            billRateVO.setTotal(0L);
        }
        bizResult.data.put("billRateVO", billRateVO);
        bizResult.success = true;
        return bizResult;
    }

    @Override
    public BizResult statEstate(StatFeeForm statFeeForm) {
        BizResult bizResult = new BizResult();
        if (statFeeForm.getVillageId() != null) {
            SysVarQuery sysVarQuery = new SysVarQuery();
            sysVarQuery.setVillageId(statFeeForm.getVillageId());
            sysVarQuery.setVarType(SysVarTypeEnum.building.name());
            sysVarQuery.setPageSize(500);
            List<SysVarDO> sysVarDOs = sysVarDAO.selectForPage(sysVarQuery);
            bizResult.data.put("buildingTypeList", sysVarDOs);
        }
        List<Long> suiteIdList = getSuiteIdList(statFeeForm);
        if (suiteIdList == null || suiteIdList.size() == 0) {
            bizResult.success = true;
            return bizResult;
        }


        Date startDate = null;
        Date endDate = null;
        if (statFeeForm.getStartDate() != null) {
            String start = statFeeForm.getStartDate() + "-01 00:00:00";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                startDate = simpleDateFormat.parse(start);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        if (statFeeForm.getEndDate() != null) {
            String end = statFeeForm.getEndDate() + "-01 00:00:00";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                Date parse = simpleDateFormat.parse(end);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(parse);
                calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
                calendar.set(Calendar.HOUR_OF_DAY, 23);
                calendar.set(Calendar.MINUTE, 59);
                calendar.set(Calendar.SECOND, 59);
                endDate = (calendar.getTime());
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        List<BillEstateDO> bill = billEstateDAO.getBill(suiteIdList, startDate, endDate, null);
        Set<Long> suiteIdSet = TransformHelper.transform2Set(bill, new Transform<BillEstateDO, Long>() {
            @Override
            public Long transform(BillEstateDO object) {
                return object.getSuiteId();
            }
        });
        if (suiteIdSet.size() == 0) {
            bizResult.success = true;
            return bizResult;
        }
        List<SuiteDO> suiteByIds = suiteDAO.getSuiteByIds(new ArrayList(suiteIdSet));
        Map<Long, SuiteDO> suiteDOMap = new HashMap<Long, SuiteDO>();
        for (SuiteDO suiteDO : suiteByIds) {
            suiteDOMap.put(suiteDO.getSuiteId(), suiteDO);
        }
        if (StatTypeEnum.office.name().equals(statFeeForm.getType())) {
            statByOffice(bizResult, bill, suiteDOMap
                    , statFeeForm, startDate, endDate, suiteIdList);
        } else if (StatTypeEnum.type.name().equals(statFeeForm.getType())) {
            statByBuildingType(bizResult, bill, suiteDOMap
                    , statFeeForm, startDate, endDate, suiteIdList);
        } else if (StatTypeEnum.manage.name().equals(statFeeForm.getType())) {
            statByManage(bizResult, bill, suiteDOMap
                    , statFeeForm, startDate, endDate, suiteIdList);
        } else if (StatTypeEnum.village.name().equals(statFeeForm.getType())) {
            statByVillage(bizResult, bill, suiteDOMap
                    , statFeeForm, startDate, endDate, suiteIdList);
        } else if (StatTypeEnum.building.name().equals(statFeeForm.getType())) {
            statByBuilding(bizResult, bill, suiteDOMap
                    , statFeeForm, startDate, endDate, suiteIdList);
        }


        bizResult.success = true;
        return bizResult;
    }


    private void statByOffice(BizResult bizResult, List<BillEstateDO> bill, Map<Long, SuiteDO> suiteDOMap, StatFeeForm statFeeForm, Date startDate, Date endDate, List<Long> suiteIdList) {
        //按办公室分组
        Map<Long, List<BillEstateDO>> billMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : bill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            List<BillEstateDO> billEstateDOList = billMap.get(suiteDO.getOfficeVarId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                billMap.put(suiteDO.getOfficeVarId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        SysVarQuery sysVarQuery = new SysVarQuery();
        sysVarQuery.setPageSize(500);
        sysVarQuery.setVillageId(statFeeForm.getVillageId());
        sysVarQuery.setVarType(SysVarTypeEnum.office.name());
        List<SysVarDO> sysVarDOs = sysVarDAO.selectForView(sysVarQuery);
        Map<Long, SysVarDO> sysVarDOMap = new HashMap<Long, SysVarDO>();
        for (SysVarDO sysVarDO : sysVarDOs) {
            sysVarDOMap.put(sysVarDO.getVarId(), sysVarDO);
        }
        Map<String, BillRateVO> billRateVOMap = new HashMap<String, BillRateVO>();
        Iterator<Map.Entry<Long, List<BillEstateDO>>> iterator = billMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = iterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String officeName = "未分类";
            if (sysVarDO != null) {
                officeName = sysVarDO.getVarValue();
            }
            BillRateVO billRateVO = statRate(estateDOList);
            //统计总房数
            Set<Long> totalSuiteIdSet = TransformHelper.transform2Set(estateDOList, new Transform<BillEstateDO, Long>() {
                @Override
                public Long transform(BillEstateDO object) {
                    return object.getSuiteId();
                }
            });
            billRateVO.setSuiteTotal(totalSuiteIdSet.size());
            //统计交房数
            int deliveryTotal = 0;
            for (Long suiteId : totalSuiteIdSet) {
                SuiteDO suiteDO = suiteDOMap.get(suiteId);
                if (suiteDO.getGmtDelivery() != null) {
                    deliveryTotal++;
                }
            }
            billRateVO.setSuiteDeliverTotal(deliveryTotal);
            billRateVOMap.put(officeName, billRateVO);
        }

        bizResult.data.put("billRateVOMap", billRateVOMap);
        //统计历年欠费
        List<BillEstateDO> unpayBill = billEstateDAO.getBill(suiteIdList, null, startDate, 0);
        Map<Long, List<BillEstateDO>> unpayBillMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : unpayBill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            List<BillEstateDO> billEstateDOList = unpayBillMap.get(suiteDO.getOfficeVarId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                unpayBillMap.put(suiteDO.getOfficeVarId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        Iterator<Map.Entry<Long, List<BillEstateDO>>> unpayIterator = unpayBillMap.entrySet().iterator();
        while (unpayIterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = unpayIterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String officeName = "未分类";
            if (sysVarDO != null) {
                officeName = sysVarDO.getVarValue();
            }
            long fee = 0;
            for (BillEstateDO billEstateDO : estateDOList) {
                fee += billEstateDO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(officeName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setUnpayTotal(fee);
                billRateVOMap.put(officeName, billRateVO);
            } else {
                billRateVO.setUnpayTotal(fee);
            }
        }

        //统计当期预收
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        if (calendar.get(Calendar.MONTH) != 11) {
            calendar.set(Calendar.MONTH, 11);
        }
        List<BillEstateDO> preBill = billEstateDAO.getBill(suiteIdList, endDate, calendar.getTime(), 1);
        Map<Long, List<BillEstateDO>> preBillMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : preBill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            List<BillEstateDO> billEstateDOList = preBillMap.get(suiteDO.getOfficeVarId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                preBillMap.put(suiteDO.getOfficeVarId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        Iterator<Map.Entry<Long, List<BillEstateDO>>> preIterator = preBillMap.entrySet().iterator();
        while (preIterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = preIterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String officeName = "未分类";
            if (sysVarDO != null) {
                officeName = sysVarDO.getVarValue();
            }
            long fee = 0;
            for (BillEstateDO billEstateDO : estateDOList) {
                fee += billEstateDO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(officeName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setPreTotal(fee);
                billRateVOMap.put(officeName, billRateVO);
            } else {
                billRateVO.setPreTotal(fee);
            }
        }

        //统计次年预收
        int year = calendar.get(Calendar.YEAR);
        List<BillEstateDO> preNextYearBill = billEstateDAO.getBillByYear(suiteIdList, year + 1, 1);
        Map<Long, List<BillEstateDO>> preNextYearBillMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : preNextYearBill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            List<BillEstateDO> billEstateDOList = preNextYearBillMap.get(suiteDO.getOfficeVarId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                preNextYearBillMap.put(suiteDO.getOfficeVarId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        Iterator<Map.Entry<Long, List<BillEstateDO>>> preNextYearIterator = preNextYearBillMap.entrySet().iterator();
        while (preNextYearIterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = preNextYearIterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String officeName = "未分类";
            if (sysVarDO != null) {
                officeName = sysVarDO.getVarValue();
            }
            long fee = 0;
            for (BillEstateDO billEstateDO : estateDOList) {
                fee += billEstateDO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(officeName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setPreTotalNextYear(fee);
                billRateVOMap.put(officeName, billRateVO);
            } else {
                billRateVO.setPreTotalNextYear(fee);
            }
        }
        //统计当年地产减免和自行减免
        List<BillEstateDO> currentYearBill = billEstateDAO.getBillByYear(suiteIdList, year, 1);
        Map<Long, List<BillEstateDO>> currentYearBillMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : currentYearBill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            List<BillEstateDO> billEstateDOList = currentYearBillMap.get(suiteDO.getOfficeVarId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                currentYearBillMap.put(suiteDO.getOfficeVarId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        Iterator<Map.Entry<Long, List<BillEstateDO>>> currentYearIterator = currentYearBillMap.entrySet().iterator();
        while (currentYearIterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = currentYearIterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String officeName = "未分类";
            if (sysVarDO != null) {
                officeName = sysVarDO.getVarValue();
            }
            long selfDiscount = 0;
            long dichanDiscount = 0;
            for (BillEstateDO billEstateDO : estateDOList) {
                if (billEstateDO.getDiscountSelf() != null) {
                    selfDiscount += billEstateDO.getDiscountSelf();
                }
                if (billEstateDO.getDiscountEstate() != null) {
                    dichanDiscount += billEstateDO.getDiscountEstate();
                }
            }
            BillRateVO billRateVO = billRateVOMap.get(officeName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setDichanDiscountAllYear(dichanDiscount);
                billRateVO.setSelfDiscountAllYear(selfDiscount);
                billRateVOMap.put(officeName, billRateVO);
            } else {
                billRateVO.setDichanDiscountAllYear(dichanDiscount);
                billRateVO.setSelfDiscountAllYear(selfDiscount);
            }
        }

        //移除不需要统计的
        if (statFeeForm.getSubType() != null) {
            SysVarDO sysVarDO = sysVarDOMap.get(statFeeForm.getSubType());
            if (sysVarDO != null) {
                Iterator<String> iterator1 = billRateVOMap.keySet().iterator();
                if (iterator1.hasNext()) {
                    String key = iterator1.next();
                    if (!key.equals(sysVarDO.getVarValue())) {
                        billRateVOMap.remove(key);
                    }
                }
            }
        }
    }


    private void statByVillage(BizResult bizResult, List<BillEstateDO> bill, Map<Long, SuiteDO> suiteDOMap, StatFeeForm statFeeForm, Date startDate, Date endDate, List<Long> suiteIdList) {
        //按小区分组
        Map<String, BillRateVO> billRateVOMap = new HashMap<String, BillRateVO>();
        VillageDO villageById = villageDAO.getVillageById(statFeeForm.getVillageId());
        BillRateVO billRateVO = statRate(bill);
        //统计总房数
        Set<Long> totalSuiteIdSet = TransformHelper.transform2Set(bill, new Transform<BillEstateDO, Long>() {
            @Override
            public Long transform(BillEstateDO object) {
                return object.getSuiteId();
            }
        });
        billRateVO.setSuiteTotal(totalSuiteIdSet.size());
        //统计交房数
        int deliveryTotal = 0;
        for (Long suiteId : totalSuiteIdSet) {
            SuiteDO suiteDO = suiteDOMap.get(suiteId);
            if (suiteDO.getGmtDelivery() != null) {
                deliveryTotal++;
            }
        }
        billRateVO.setSuiteDeliverTotal(deliveryTotal);
        billRateVOMap.put(villageById.getVillageName(), billRateVO);


        bizResult.data.put("billRateVOMap", billRateVOMap);
        //统计历年欠费
        List<BillEstateDO> unpayBill = billEstateDAO.getBill(suiteIdList, null, startDate, 0);
        long fee = 0;
        for (BillEstateDO billEstateDO : unpayBill) {
            fee += billEstateDO.getPayTotal();
        }
        billRateVO.setUnpayTotal(fee);

        //统计当期预收
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        if (calendar.get(Calendar.MONTH) != 11) {
            calendar.set(Calendar.MONTH, 11);
        }
        List<BillEstateDO> preBill = billEstateDAO.getBill(suiteIdList, endDate, calendar.getTime(), 1);

        fee = 0;
        for (BillEstateDO billEstateDO : preBill) {
            fee += billEstateDO.getPayTotal();
        }

        billRateVO.setPreTotal(fee);


        //统计次年预收
        int year = calendar.get(Calendar.YEAR);
        List<BillEstateDO> preNextYearBill = billEstateDAO.getBillByYear(suiteIdList, year + 1, 1);
        fee = 0;
        for (BillEstateDO billEstateDO : preNextYearBill) {
            fee += billEstateDO.getPayTotal();
        }

        billRateVO.setPreTotalNextYear(fee);


        //统计当年地产减免和自行减免
        List<BillEstateDO> currentYearBill = billEstateDAO.getBillByYear(suiteIdList, year, 1);

        long selfDiscount = 0;
        long dichanDiscount = 0;
        for (BillEstateDO billEstateDO : currentYearBill) {
            if (billEstateDO.getDiscountSelf() != null) {
                selfDiscount += billEstateDO.getDiscountSelf();
            }
            if (billEstateDO.getDiscountEstate() != null) {
                dichanDiscount += billEstateDO.getDiscountEstate();
            }
        }

        billRateVO.setDichanDiscountAllYear(dichanDiscount);
        billRateVO.setSelfDiscountAllYear(selfDiscount);


    }


    private void statByManage(BizResult bizResult, List<BillEstateDO> bill, Map<Long, SuiteDO> suiteDOMap
            , StatFeeForm statFeeForm, Date startDate, Date endDate, List<Long> suiteIdList) {
        //按办公室分组
        Map<Long, List<BillEstateDO>> billMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : bill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            List<BillEstateDO> billEstateDOList = billMap.get(suiteDO.getEmployeeId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                billMap.put(suiteDO.getEmployeeId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        OfficeEmployeeQuery officeEmployeeQuery = new OfficeEmployeeQuery();
        officeEmployeeQuery.setVillageId(statFeeForm.getVillageId());
        officeEmployeeQuery.setPageSize(5000);
        List<OfficeEmployeeDO> officeEmployeeDOList = officeEmployeeDAO.selectForPage(officeEmployeeQuery);
        Map<Long, OfficeEmployeeDO> officeEmployeeDOMap = new HashMap<Long, OfficeEmployeeDO>();
        for (OfficeEmployeeDO officeEmployeeDO : officeEmployeeDOList) {
            officeEmployeeDOMap.put(officeEmployeeDO.getEmployeeId(), officeEmployeeDO);
        }
        Map<String, BillRateVO> billRateVOMap = new HashMap<String, BillRateVO>();
        Iterator<Map.Entry<Long, List<BillEstateDO>>> iterator = billMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = iterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            OfficeEmployeeDO officeEmployeeDO = officeEmployeeDOMap.get(varId);
            String groupName = "未分类";
            if (officeEmployeeDO != null) {
                groupName = officeEmployeeDO.getUserName();
            }
            BillRateVO billRateVO = statRate(estateDOList);
            //统计总房数
            Set<Long> totalSuiteIdSet = TransformHelper.transform2Set(estateDOList, new Transform<BillEstateDO, Long>() {
                @Override
                public Long transform(BillEstateDO object) {
                    return object.getSuiteId();
                }
            });
            billRateVO.setSuiteTotal(totalSuiteIdSet.size());
            //统计交房数
            int deliveryTotal = 0;
            for (Long suiteId : totalSuiteIdSet) {
                SuiteDO suiteDO = suiteDOMap.get(suiteId);
                if (suiteDO.getGmtDelivery() != null) {
                    deliveryTotal++;
                }
            }
            billRateVO.setSuiteDeliverTotal(deliveryTotal);
            billRateVOMap.put(groupName, billRateVO);
        }

        bizResult.data.put("billRateVOMap", billRateVOMap);
        //统计历年欠费
        List<BillEstateDO> unpayBill = billEstateDAO.getBill(suiteIdList, null, startDate, 0);
        Map<Long, List<BillEstateDO>> unpayBillMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : unpayBill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            List<BillEstateDO> billEstateDOList = unpayBillMap.get(suiteDO.getEmployeeId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                unpayBillMap.put(suiteDO.getEmployeeId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        Iterator<Map.Entry<Long, List<BillEstateDO>>> unpayIterator = unpayBillMap.entrySet().iterator();
        while (unpayIterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = unpayIterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            OfficeEmployeeDO officeEmployeeDO = officeEmployeeDOMap.get(varId);
            String groupName = "未分类";
            if (officeEmployeeDO != null) {
                groupName = officeEmployeeDO.getUserName();
            }
            long fee = 0;
            for (BillEstateDO billEstateDO : estateDOList) {
                fee += billEstateDO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setUnpayTotal(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setUnpayTotal(fee);
            }
        }

        //统计当期预收
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        if (calendar.get(Calendar.MONTH) != 11) {
            calendar.set(Calendar.MONTH, 11);
        }
        List<BillEstateDO> preBill = billEstateDAO.getBill(suiteIdList, endDate, calendar.getTime(), 1);
        Map<Long, List<BillEstateDO>> preBillMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : preBill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            List<BillEstateDO> billEstateDOList = preBillMap.get(suiteDO.getEmployeeId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                preBillMap.put(suiteDO.getOfficeVarId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        Iterator<Map.Entry<Long, List<BillEstateDO>>> preIterator = preBillMap.entrySet().iterator();
        while (preIterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = preIterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            OfficeEmployeeDO officeEmployeeDO = officeEmployeeDOMap.get(varId);
            String groupName = "未分类";
            if (officeEmployeeDO != null) {
                groupName = officeEmployeeDO.getUserName();
            }
            long fee = 0;
            for (BillEstateDO billEstateDO : estateDOList) {
                fee += billEstateDO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setPreTotal(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setPreTotal(fee);
            }
        }

        //统计次年预收
        int year = calendar.get(Calendar.YEAR);
        List<BillEstateDO> preNextYearBill = billEstateDAO.getBillByYear(suiteIdList, year + 1, 1);
        Map<Long, List<BillEstateDO>> preNextYearBillMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : preNextYearBill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            List<BillEstateDO> billEstateDOList = preNextYearBillMap.get(suiteDO.getEmployeeId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                preNextYearBillMap.put(suiteDO.getEmployeeId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        Iterator<Map.Entry<Long, List<BillEstateDO>>> preNextYearIterator = preNextYearBillMap.entrySet().iterator();
        while (preNextYearIterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = preNextYearIterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            OfficeEmployeeDO officeEmployeeDO = officeEmployeeDOMap.get(varId);
            String groupName = "未分类";
            if (officeEmployeeDO != null) {
                groupName = officeEmployeeDO.getUserName();
            }
            long fee = 0;
            for (BillEstateDO billEstateDO : estateDOList) {
                fee += billEstateDO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setPreTotalNextYear(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setPreTotalNextYear(fee);
            }
        }
        //统计当年地产减免和自行减免
        List<BillEstateDO> currentYearBill = billEstateDAO.getBillByYear(suiteIdList, year, 1);
        Map<Long, List<BillEstateDO>> currentYearBillMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : currentYearBill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            List<BillEstateDO> billEstateDOList = currentYearBillMap.get(suiteDO.getEmployeeId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                currentYearBillMap.put(suiteDO.getEmployeeId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        Iterator<Map.Entry<Long, List<BillEstateDO>>> currentYearIterator = currentYearBillMap.entrySet().iterator();
        while (currentYearIterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = currentYearIterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            OfficeEmployeeDO officeEmployeeDO = officeEmployeeDOMap.get(varId);
            String groupName = "未分类";
            if (officeEmployeeDO != null) {
                groupName = officeEmployeeDO.getUserName();
            }
            long selfDiscount = 0;
            long dichanDiscount = 0;
            for (BillEstateDO billEstateDO : estateDOList) {
                if (billEstateDO.getDiscountSelf() != null) {
                    selfDiscount += billEstateDO.getDiscountSelf();
                }
                if (billEstateDO.getDiscountEstate() != null) {
                    dichanDiscount += billEstateDO.getDiscountEstate();
                }
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setDichanDiscountAllYear(dichanDiscount);
                billRateVO.setSelfDiscountAllYear(selfDiscount);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setDichanDiscountAllYear(dichanDiscount);
                billRateVO.setSelfDiscountAllYear(selfDiscount);
            }
        }

        //移除不需要统计的
        if (statFeeForm.getSubType() != null) {
            OfficeEmployeeDO officeEmployeeDO = officeEmployeeDOMap.get(statFeeForm.getSubType());
            if (officeEmployeeDO != null) {
                Iterator<String> iterator1 = billRateVOMap.keySet().iterator();
                if (iterator1.hasNext()) {
                    String key = iterator1.next();
                    if (!key.equals(officeEmployeeDO.getUserName())) {
                        billRateVOMap.remove(key);
                    }
                }
            }
        }
    }

    private void statByBuilding(BizResult bizResult, List<BillEstateDO> bill, Map<Long, SuiteDO> suiteDOMap
            , StatFeeForm statFeeForm, Date startDate, Date endDate, List<Long> suiteIdList) {
        //按楼栋分组
        BuildingQuery buildingQuery = new BuildingQuery();
        buildingQuery.setVillageId(statFeeForm.getVillageId());
        List<BuildingDO> buildingDOs = buildingDAO.selectForPage(buildingQuery);
        Map<Long, BuildingDO> buildingDOMap = new HashMap<Long, BuildingDO>();
        for (BuildingDO buildingDO : buildingDOs) {
            buildingDOMap.put(buildingDO.getBuildingId(), buildingDO);
        }

        List<Long> buildingIdList = TransformHelper.transform(buildingDOs, new Transform<BuildingDO, Long>() {
            @Override
            public Long transform(BuildingDO object) {
                return object.getBuildingId();
            }
        });
        if (buildingIdList.size() == 0) {
            bizResult.success = true;
            return;
        }

        Map<Long, Long> buildingSuiteMap = new HashMap<Long, Long>();
        for (Long buildingId : buildingIdList) {
            UnitQuery unitQuery = new UnitQuery();
            unitQuery.setPageSize(10000);
            unitQuery.setBuildingId(buildingId);
            List<UnitDO> unitDOs = unitDAO.selectForPage(unitQuery);
            List<Long> unitIdList = TransformHelper.transform(unitDOs, new Transform<UnitDO, Long>() {
                @Override
                public Long transform(UnitDO object) {
                    return object.getUnitId();
                }
            });
            if (unitIdList.size() == 0) {
                continue;
            }

            SuiteQuery suiteQuery = new SuiteQuery();
            suiteQuery.setPageSize(10000);
            suiteQuery.setUnitIdList(unitIdList);
            List<SuiteDO> suiteDOs = suiteDAO.selectForPage(suiteQuery);
            for (SuiteDO suiteDO : suiteDOs) {
                buildingSuiteMap.put(suiteDO.getSuiteId(), buildingId);
            }
        }


        Map<Long, List<BillEstateDO>> billMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : bill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            Long buildingId = buildingSuiteMap.get(suiteDO.getSuiteId());
            List<BillEstateDO> billEstateDOList = billMap.get(buildingId);
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                billMap.put(buildingId, billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }

        Map<String, BillRateVO> billRateVOMap = new HashMap<String, BillRateVO>();
        Iterator<Map.Entry<Long, List<BillEstateDO>>> iterator = billMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = iterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            BuildingDO buildingDO = buildingDOMap.get(varId);
            String groupName = "未分类";
            if (buildingDO != null) {
                groupName = buildingDO.getBuildingName();
            }
            BillRateVO billRateVO = statRate(estateDOList);
            //统计总房数
            Set<Long> totalSuiteIdSet = TransformHelper.transform2Set(estateDOList, new Transform<BillEstateDO, Long>() {
                @Override
                public Long transform(BillEstateDO object) {
                    return object.getSuiteId();
                }
            });
            billRateVO.setSuiteTotal(totalSuiteIdSet.size());
            //统计交房数
            int deliveryTotal = 0;
            for (Long suiteId : totalSuiteIdSet) {
                SuiteDO suiteDO = suiteDOMap.get(suiteId);
                if (suiteDO.getGmtDelivery() != null) {
                    deliveryTotal++;
                }
            }
            billRateVO.setSuiteDeliverTotal(deliveryTotal);
            billRateVOMap.put(groupName, billRateVO);
        }

        bizResult.data.put("billRateVOMap", billRateVOMap);
        //统计历年欠费
        List<BillEstateDO> unpayBill = billEstateDAO.getBill(suiteIdList, null, startDate, 0);
        Map<Long, List<BillEstateDO>> unpayBillMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : unpayBill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            List<BillEstateDO> billEstateDOList = unpayBillMap.get(suiteDO.getEmployeeId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                unpayBillMap.put(suiteDO.getEmployeeId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        Iterator<Map.Entry<Long, List<BillEstateDO>>> unpayIterator = unpayBillMap.entrySet().iterator();
        while (unpayIterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = unpayIterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            BuildingDO buildingDO = buildingDOMap.get(varId);
            String groupName = "未分类";
            if (buildingDO != null) {
                groupName = buildingDO.getBuildingName();
            }
            long fee = 0;
            for (BillEstateDO billEstateDO : estateDOList) {
                fee += billEstateDO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setUnpayTotal(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setUnpayTotal(fee);
            }
        }

        //统计当期预收
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        if (calendar.get(Calendar.MONTH) != 11) {
            calendar.set(Calendar.MONTH, 11);
        }
        List<BillEstateDO> preBill = billEstateDAO.getBill(suiteIdList, endDate, calendar.getTime(), 1);
        Map<Long, List<BillEstateDO>> preBillMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : preBill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            List<BillEstateDO> billEstateDOList = preBillMap.get(suiteDO.getEmployeeId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                preBillMap.put(suiteDO.getOfficeVarId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        Iterator<Map.Entry<Long, List<BillEstateDO>>> preIterator = preBillMap.entrySet().iterator();
        while (preIterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = preIterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            BuildingDO buildingDO = buildingDOMap.get(varId);
            String groupName = "未分类";
            if (buildingDO != null) {
                groupName = buildingDO.getBuildingName();
            }
            long fee = 0;
            for (BillEstateDO billEstateDO : estateDOList) {
                fee += billEstateDO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setPreTotal(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setPreTotal(fee);
            }
        }

        //统计次年预收
        int year = calendar.get(Calendar.YEAR);
        List<BillEstateDO> preNextYearBill = billEstateDAO.getBillByYear(suiteIdList, year + 1, 1);
        Map<Long, List<BillEstateDO>> preNextYearBillMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : preNextYearBill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            List<BillEstateDO> billEstateDOList = preNextYearBillMap.get(suiteDO.getEmployeeId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                preNextYearBillMap.put(suiteDO.getEmployeeId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        Iterator<Map.Entry<Long, List<BillEstateDO>>> preNextYearIterator = preNextYearBillMap.entrySet().iterator();
        while (preNextYearIterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = preNextYearIterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            BuildingDO buildingDO = buildingDOMap.get(varId);
            String groupName = "未分类";
            if (buildingDO != null) {
                groupName = buildingDO.getBuildingName();
            }
            long fee = 0;
            for (BillEstateDO billEstateDO : estateDOList) {
                fee += billEstateDO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setPreTotalNextYear(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setPreTotalNextYear(fee);
            }
        }
        //统计当年地产减免和自行减免
        List<BillEstateDO> currentYearBill = billEstateDAO.getBillByYear(suiteIdList, year, 1);
        Map<Long, List<BillEstateDO>> currentYearBillMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : currentYearBill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            List<BillEstateDO> billEstateDOList = currentYearBillMap.get(suiteDO.getEmployeeId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                currentYearBillMap.put(suiteDO.getEmployeeId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        Iterator<Map.Entry<Long, List<BillEstateDO>>> currentYearIterator = currentYearBillMap.entrySet().iterator();
        while (currentYearIterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = currentYearIterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            BuildingDO buildingDO = buildingDOMap.get(varId);
            String groupName = "未分类";
            if (buildingDO != null) {
                groupName = buildingDO.getBuildingName();
            }
            long selfDiscount = 0;
            long dichanDiscount = 0;
            for (BillEstateDO billEstateDO : estateDOList) {
                if (billEstateDO.getDiscountSelf() != null) {
                    selfDiscount += billEstateDO.getDiscountSelf();
                }
                if (billEstateDO.getDiscountEstate() != null) {
                    dichanDiscount += billEstateDO.getDiscountEstate();
                }
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setDichanDiscountAllYear(dichanDiscount);
                billRateVO.setSelfDiscountAllYear(selfDiscount);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setDichanDiscountAllYear(dichanDiscount);
                billRateVO.setSelfDiscountAllYear(selfDiscount);
            }
        }

        //移除不需要统计的
        if (statFeeForm.getSubType() != null) {
            BuildingDO buildingDO = buildingDOMap.get(statFeeForm.getSubType());
            if (buildingDO != null) {
                Iterator<String> iterator1 = billRateVOMap.keySet().iterator();
                if (iterator1.hasNext()) {
                    String key = iterator1.next();
                    if (!key.equals(buildingDO.getBuildingName())) {
                        billRateVOMap.remove(key);
                    }
                }
            }
        }
    }


    private void statByBuildingType(BizResult bizResult, List<BillEstateDO> bill, Map<Long, SuiteDO> suiteDOMap
            , StatFeeForm statFeeForm, Date startDate, Date endDate, List<Long> suiteIdList) {
        //按建筑类型分组
        BuildingQuery buildingQuery = new BuildingQuery();
        buildingQuery.setVillageId(statFeeForm.getVillageId());
        List<BuildingDO> buildingDOs = buildingDAO.selectForPage(buildingQuery);
        Map<Long, BuildingDO> buildingDOMap = new HashMap<Long, BuildingDO>();
        for (BuildingDO buildingDO : buildingDOs) {
            buildingDOMap.put(buildingDO.getBuildingId(), buildingDO);
        }

        List<Long> buildingIdList = TransformHelper.transform(buildingDOs, new Transform<BuildingDO, Long>() {
            @Override
            public Long transform(BuildingDO object) {
                return object.getBuildingId();
            }
        });
        if (buildingIdList.size() == 0) {
            bizResult.success = true;
            return;
        }

        Map<Long, Long> buildingSuiteMap = new HashMap<Long, Long>();
        for (Long buildingId : buildingIdList) {
            UnitQuery unitQuery = new UnitQuery();
            unitQuery.setPageSize(10000);
            unitQuery.setBuildingId(buildingId);
            List<UnitDO> unitDOs = unitDAO.selectForPage(unitQuery);
            List<Long> unitIdList = TransformHelper.transform(unitDOs, new Transform<UnitDO, Long>() {
                @Override
                public Long transform(UnitDO object) {
                    return object.getUnitId();
                }
            });
            if (unitIdList.size() == 0) {
                continue;
            }

            SuiteQuery suiteQuery = new SuiteQuery();
            suiteQuery.setPageSize(10000);
            suiteQuery.setUnitIdList(unitIdList);
            List<SuiteDO> suiteDOs = suiteDAO.selectForPage(suiteQuery);
            for (SuiteDO suiteDO : suiteDOs) {
                buildingSuiteMap.put(suiteDO.getSuiteId(), buildingId);
            }
        }

        SysVarQuery sysVarQuery = new SysVarQuery();
        sysVarQuery.setVillageId(statFeeForm.getVillageId());
        sysVarQuery.setPageSize(500);
        sysVarQuery.setVarType(SysVarTypeEnum.building.name());
        List<SysVarDO> sysVarDOs = sysVarDAO.selectForView(sysVarQuery);
        Map<Long, SysVarDO> sysVarDOMap = new HashMap<Long, SysVarDO>();
        for (SysVarDO sysVarDO : sysVarDOs) {
            sysVarDOMap.put(sysVarDO.getVarId(), sysVarDO);
        }

        Map<Long, List<BillEstateDO>> billMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : bill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            //Long buildingId = buildingSuiteMap.get(suiteDO.getSuiteId());
            //BuildingDO buildingDO = buildingDOMap.get(buildingId);
            List<BillEstateDO> billEstateDOList = billMap.get(suiteDO.getBuildingTypeId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                billMap.put(suiteDO.getBuildingTypeId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }

        Map<String, BillRateVO> billRateVOMap = new HashMap<String, BillRateVO>();
        Iterator<Map.Entry<Long, List<BillEstateDO>>> iterator = billMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = iterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String groupName = "未分类";
            if (sysVarDO != null) {
                groupName = sysVarDO.getVarValue();
            }
            BillRateVO billRateVO = statRate(estateDOList);
            //统计总房数
            Set<Long> totalSuiteIdSet = TransformHelper.transform2Set(estateDOList, new Transform<BillEstateDO, Long>() {
                @Override
                public Long transform(BillEstateDO object) {
                    return object.getSuiteId();
                }
            });
            billRateVO.setSuiteTotal(totalSuiteIdSet.size());
            //统计交房数
            int deliveryTotal = 0;
            for (Long suiteId : totalSuiteIdSet) {
                SuiteDO suiteDO = suiteDOMap.get(suiteId);
                if (suiteDO.getGmtDelivery() != null) {
                    deliveryTotal++;
                }
            }
            billRateVO.setSuiteDeliverTotal(deliveryTotal);
            billRateVOMap.put(groupName, billRateVO);
        }

        bizResult.data.put("billRateVOMap", billRateVOMap);
        //统计历年欠费
        List<BillEstateDO> unpayBill = billEstateDAO.getBill(suiteIdList, null, startDate, 0);
        Map<Long, List<BillEstateDO>> unpayBillMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : unpayBill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            //Long buildingId = buildingSuiteMap.get(suiteDO.getSuiteId());
            //BuildingDO buildingDO = buildingDOMap.get(buildingId);
            List<BillEstateDO> billEstateDOList = unpayBillMap.get(suiteDO.getBuildingTypeId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                unpayBillMap.put(suiteDO.getBuildingTypeId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        Iterator<Map.Entry<Long, List<BillEstateDO>>> unpayIterator = unpayBillMap.entrySet().iterator();
        while (unpayIterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = unpayIterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String groupName = "未分类";
            if (sysVarDO != null) {
                groupName = sysVarDO.getVarValue();
            }
            long fee = 0;
            for (BillEstateDO billEstateDO : estateDOList) {
                fee += billEstateDO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setUnpayTotal(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setUnpayTotal(fee);
            }
        }

        //统计当期预收
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        if (calendar.get(Calendar.MONTH) != 11) {
            calendar.set(Calendar.MONTH, 11);
        }
        List<BillEstateDO> preBill = billEstateDAO.getBill(suiteIdList, endDate, calendar.getTime(), 1);
        Map<Long, List<BillEstateDO>> preBillMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : preBill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            //Long buildingId = buildingSuiteMap.get(suiteDO.getSuiteId());
            //BuildingDO buildingDO = buildingDOMap.get(buildingId);
            List<BillEstateDO> billEstateDOList = preBillMap.get(suiteDO.getBuildingTypeId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                preBillMap.put(suiteDO.getBuildingTypeId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        Iterator<Map.Entry<Long, List<BillEstateDO>>> preIterator = preBillMap.entrySet().iterator();
        while (preIterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = preIterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String groupName = "未分类";
            if (sysVarDO != null) {
                groupName = sysVarDO.getVarValue();
            }
            long fee = 0;
            for (BillEstateDO billEstateDO : estateDOList) {
                fee += billEstateDO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setPreTotal(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setPreTotal(fee);
            }
        }

        //统计次年预收
        int year = calendar.get(Calendar.YEAR);
        List<BillEstateDO> preNextYearBill = billEstateDAO.getBillByYear(suiteIdList, year + 1, 1);
        Map<Long, List<BillEstateDO>> preNextYearBillMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : preNextYearBill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
            //Long buildingId = buildingSuiteMap.get(suiteDO.getSuiteId());
            //BuildingDO buildingDO = buildingDOMap.get(buildingId);
            List<BillEstateDO> billEstateDOList = preNextYearBillMap.get(suiteDO.getBuildingTypeId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                preNextYearBillMap.put(suiteDO.getBuildingTypeId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        Iterator<Map.Entry<Long, List<BillEstateDO>>> preNextYearIterator = preNextYearBillMap.entrySet().iterator();
        while (preNextYearIterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = preNextYearIterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String groupName = "未分类";
            if (sysVarDO != null) {
                groupName = sysVarDO.getVarValue();
            }
            long fee = 0;
            for (BillEstateDO billEstateDO : estateDOList) {
                fee += billEstateDO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setPreTotalNextYear(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setPreTotalNextYear(fee);
            }
        }
        //统计当年地产减免和自行减免
        List<BillEstateDO> currentYearBill = billEstateDAO.getBillByYear(suiteIdList, year, 1);
        Map<Long, List<BillEstateDO>> currentYearBillMap = new HashMap<Long, List<BillEstateDO>>();
        for (BillEstateDO billEstateDO : currentYearBill) {
            SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
           // Long buildingId = buildingSuiteMap.get(suiteDO.getSuiteId());
           // BuildingDO buildingDO = buildingDOMap.get(buildingId);
            List<BillEstateDO> billEstateDOList = currentYearBillMap.get(suiteDO.getBuildingTypeId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillEstateDO>();
                billEstateDOList.add(billEstateDO);
                currentYearBillMap.put(suiteDO.getBuildingTypeId(), billEstateDOList);
            } else {
                billEstateDOList.add(billEstateDO);
            }
        }
        Iterator<Map.Entry<Long, List<BillEstateDO>>> currentYearIterator = currentYearBillMap.entrySet().iterator();
        while (currentYearIterator.hasNext()) {
            Map.Entry<Long, List<BillEstateDO>> next = currentYearIterator.next();
            Long varId = next.getKey();
            List<BillEstateDO> estateDOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String groupName = "未分类";
            if (sysVarDO != null) {
                groupName = sysVarDO.getVarValue();
            }
            long selfDiscount = 0;
            long dichanDiscount = 0;
            for (BillEstateDO billEstateDO : estateDOList) {
                if (billEstateDO.getDiscountSelf() != null) {
                    selfDiscount += billEstateDO.getDiscountSelf();
                }
                if (billEstateDO.getDiscountEstate() != null) {
                    dichanDiscount += billEstateDO.getDiscountEstate();
                }
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setDichanDiscountAllYear(dichanDiscount);
                billRateVO.setSelfDiscountAllYear(selfDiscount);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setDichanDiscountAllYear(dichanDiscount);
                billRateVO.setSelfDiscountAllYear(selfDiscount);
            }
        }


        //移除不需要统计的
        if (statFeeForm.getSubType() != null) {
            SysVarDO sysVarDO = sysVarDOMap.get(statFeeForm.getSubType());
            if (sysVarDO != null) {
                Iterator<String> iterator1 = billRateVOMap.keySet().iterator();
                if (iterator1.hasNext()) {
                    String key = iterator1.next();
                    if (!key.equals(sysVarDO.getVarValue())) {
                        billRateVOMap.remove(key);
                    }
                }
            }
        }
    }


    private BillRateVO statWaterElecRate(List<BillWaterElecVO> billWaterElecVOList) {
        BillRateVO billRateVO = new BillRateVO();
        if (billWaterElecVOList == null || billWaterElecVOList.size() == 0) {
            return billRateVO;
        }
        long payed = 0;
        long unpayed = 0;
        long selfDiscount = 0;
        long dichanDiscount = 0;
        for (BillWaterElecVO billWaterElecVO : billWaterElecVOList) {
            if (billWaterElecVO.getIsPayed().intValue() == BooleanEnum.TRUE.getVal()) {
                payed += billWaterElecVO.getPayTotal();
            } else {
                unpayed += billWaterElecVO.getPayTotal();
            }
            if (billWaterElecVO.getDiscountSelf() != null) {
                selfDiscount += billWaterElecVO.getDiscountSelf();
            }
            if (billWaterElecVO.getDiscountEstate() != null) {
                dichanDiscount += billWaterElecVO.getDiscountEstate();
            }

        }
        billRateVO.setTotal(payed + unpayed);
        billRateVO.setPayed(payed);
        billRateVO.setDichanDiscount(dichanDiscount);
        billRateVO.setSelfDiscount(selfDiscount);
        billRateVO.setRate(getRate(billRateVO.getPayed(), billRateVO.getTotal()));
        billRateVO.setRateDiscount(getRate(billRateVO.getSelfDiscount() + billRateVO.getDichanDiscount(), billRateVO.getTotal()));
        return billRateVO;
    }


    private BillRateVO statRate(List<BillEstateDO> estateDOList) {
        BillRateVO billRateVO = new BillRateVO();
        if (estateDOList == null || estateDOList.size() == 0) {
            return billRateVO;
        }
        long payed = 0;
        long unpayed = 0;
        long selfDiscount = 0;
        long dichanDiscount = 0;
        for (BillEstateDO billEstateDO : estateDOList) {
            if (billEstateDO.getIsPayed().intValue() == BooleanEnum.TRUE.getVal()) {
                payed += billEstateDO.getPayTotal();
            } else {
                unpayed += billEstateDO.getPayTotal();
            }
            if (billEstateDO.getDiscountSelf() != null) {
                selfDiscount += billEstateDO.getDiscountSelf();
            }
            if (billEstateDO.getDiscountEstate() != null) {
                dichanDiscount += billEstateDO.getDiscountEstate();
            }

        }
        billRateVO.setTotal(payed + unpayed);
        billRateVO.setPayed(payed);
        billRateVO.setDichanDiscount(dichanDiscount);
        billRateVO.setSelfDiscount(selfDiscount);
        billRateVO.setRate(getRate(billRateVO.getPayed(), billRateVO.getTotal()));
        billRateVO.setRateDiscount(getRate(billRateVO.getSelfDiscount() + billRateVO.getDichanDiscount(), billRateVO.getTotal()));
        return billRateVO;
    }

    @Override
    public BizResult statCharge(StatFeeForm statFeeForm) {
        BizResult bizResult = new BizResult();
        if (!StringUtils.hasText(statFeeForm.getStartDate())) {
            bizResult.success = true;
            return bizResult;
        }
        if (!StringUtils.hasText(statFeeForm.getEndDate())) {
            bizResult.success = true;
            return bizResult;
        }
        List<Long> suiteIdList = getSuiteIdList(statFeeForm);
        if (suiteIdList == null || suiteIdList.size() == 0) {
            bizResult.success = true;
            return bizResult;
        }
        String startDate = statFeeForm.getStartDate() + " 00:00:00";
        String endDate = statFeeForm.getEndDate() + " 23:59:59";


        List<BillPayDO> billPayDOs = billPayDAO.statPay(suiteIdList, startDate, endDate);
        bizResult.data.put("billPayList", billPayDOs);
        bizResult.success = true;
        return bizResult;
    }

    @Override
    public BizResult statDelivery(StatFeeForm statFeeForm) {
        BizResult bizResult = new BizResult();
        if (statFeeForm.getVillageId() == null) {
            bizResult.success = true;
            return bizResult;
        }
        Map<String,List<Long>> group = new HashMap<String, List<Long>>();
        if (StatTypeEnum.office.name().equals(statFeeForm.getType())) {
            group = groupSuiteByOffice(statFeeForm.getVillageId());
        } else if (StatTypeEnum.type.name().equals(statFeeForm.getType())) {
            group = groupSuiteByType(statFeeForm.getVillageId());
        } else if (StatTypeEnum.manage.name().equals(statFeeForm.getType())) {
            group = groupSuiteByManage(statFeeForm.getVillageId());
        } else if (StatTypeEnum.village.name().equals(statFeeForm.getType())) {
            group = groupSuiteByVillage(statFeeForm.getVillageId());
        } else if (StatTypeEnum.building.name().equals(statFeeForm.getType())) {
            group = groupSuiteByBuilding(statFeeForm.getVillageId());
        }

        Map<String, SuiteDeliveryVO> map = new LinkedHashMap<String, SuiteDeliveryVO>(group.size() * 2);
        Iterator<Map.Entry<String, List<Long>>> iterator = group.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry<String, List<Long>> next = iterator.next();
            List<Long> suiteIdList = next.getValue();
            if(suiteIdList.size()>0){
                SuiteDeliveryVO suiteDeliveryVO = new SuiteDeliveryVO();
                int stat = suiteDAO.stat(suiteIdList, null, null, null);
                suiteDeliveryVO.setTotal(stat);
                int countDelivery = suiteDAO.stat(suiteIdList, 1, null, null);
                int countCheckin = suiteDAO.stat(suiteIdList, null, 1, null);
                int countDecoration = suiteDAO.stat(suiteIdList, null, null, 1);
                suiteDeliveryVO.setCountCheckIn(countCheckin);
                suiteDeliveryVO.setCountDecoration(countDecoration);
                suiteDeliveryVO.setCountDelivery(countDelivery);
                map.put(next.getKey(), suiteDeliveryVO);
            }
        }

        bizResult.data.put("map", map);
        bizResult.success = true;
        return bizResult;
    }

    private Map<String,List<Long>> groupSuiteByBuilding(Long villageId){
        Map<String,List<Long>> result = new HashMap<String, List<Long>>();
        //按楼栋分组
        BuildingQuery buildingQuery = new BuildingQuery();
        buildingQuery.setVillageId(villageId);
        List<BuildingDO> buildingDOs = buildingDAO.selectForPage(buildingQuery);
        Map<Long, BuildingDO> buildingDOMap = new HashMap<Long, BuildingDO>();
        for (BuildingDO buildingDO : buildingDOs) {
            buildingDOMap.put(buildingDO.getBuildingId(), buildingDO);
        }

        List<Long> buildingIdList = TransformHelper.transform(buildingDOs, new Transform<BuildingDO, Long>() {
            @Override
            public Long transform(BuildingDO object) {
                return object.getBuildingId();
            }
        });
        if (buildingIdList.size() == 0) {
            return result;
        }
        for (Long buildingId : buildingIdList) {
            UnitQuery unitQuery = new UnitQuery();
            unitQuery.setPageSize(10000);
            unitQuery.setBuildingId(buildingId);
            List<UnitDO> unitDOs = unitDAO.selectForPage(unitQuery);
            List<Long> unitIdList = TransformHelper.transform(unitDOs, new Transform<UnitDO, Long>() {
                @Override
                public Long transform(UnitDO object) {
                    return object.getUnitId();
                }
            });
            if (unitIdList.size() == 0) {
                continue;
            }

            SuiteQuery suiteQuery = new SuiteQuery();
            suiteQuery.setPageSize(10000);
            suiteQuery.setUnitIdList(unitIdList);
            List<SuiteDO> suiteDOs = suiteDAO.selectForPage(suiteQuery);
            List<Long> suiteIdList = TransformHelper.transform(suiteDOs, new Transform<SuiteDO, Long>() {
                @Override
                public Long transform(SuiteDO object) {
                    return object.getUnitId();
                }
            });
            if (suiteIdList.size() == 0) {
                continue;
            }
            BuildingDO buildingDO = buildingDOMap.get(buildingId);
            String groupName;
            if(buildingDO == null){
                groupName="未分组";
            }else{
                groupName = buildingDO.getBuildingName();
            }
            result.put(groupName, suiteIdList);
        }
        return result;
    }
    private Map<String,List<Long>> groupSuiteByOffice(Long villageId){
        Map<String,List<Long>> result = new HashMap<String, List<Long>>();

        SysVarQuery sysVarQuery = new SysVarQuery();
        sysVarQuery.setPageSize(500);
        sysVarQuery.setVillageId(villageId);
        sysVarQuery.setVarType(SysVarTypeEnum.office.name());
        List<SysVarDO> sysVarDOs = sysVarDAO.selectForView(sysVarQuery);
        Map<Long, SysVarDO> sysVarDOMap = new HashMap<Long, SysVarDO>();
        for (SysVarDO sysVarDO : sysVarDOs) {
            sysVarDOMap.put(sysVarDO.getVarId(), sysVarDO);
        }

        BuildingQuery buildingQuery = new BuildingQuery();
        buildingQuery.setVillageId(villageId);
        List<BuildingDO> buildingDOs = buildingDAO.selectForPage(buildingQuery);

        List<Long> buildingIdList = TransformHelper.transform(buildingDOs, new Transform<BuildingDO, Long>() {
            @Override
            public Long transform(BuildingDO object) {
                return object.getBuildingId();
            }
        });
        if (buildingIdList.size() == 0) {
            return result;
        }
        for (Long buildingId : buildingIdList) {
            UnitQuery unitQuery = new UnitQuery();
            unitQuery.setPageSize(10000);
            unitQuery.setBuildingId(buildingId);
            List<UnitDO> unitDOs = unitDAO.selectForPage(unitQuery);
            List<Long> unitIdList = TransformHelper.transform(unitDOs, new Transform<UnitDO, Long>() {
                @Override
                public Long transform(UnitDO object) {
                    return object.getUnitId();
                }
            });
            if (unitIdList.size() == 0) {
                continue;
            }

            SuiteQuery suiteQuery = new SuiteQuery();
            suiteQuery.setPageSize(10000);
            suiteQuery.setUnitIdList(unitIdList);
            List<SuiteDO> suiteDOs = suiteDAO.selectForPage(suiteQuery);
            for(SuiteDO suiteDO:suiteDOs){
                SysVarDO sysVarDO = sysVarDOMap.get(suiteDO.getOfficeVarId());
                String groupName;
                if(sysVarDO == null){
                    groupName="未分组";
                }else{
                    groupName = sysVarDO.getVarValue();
                }
                List<Long> longs = result.get(groupName);
                if(longs == null){
                    longs = new ArrayList<Long>();
                    longs.add(suiteDO.getSuiteId());
                    result.put(groupName,longs);
                }else{
                    longs.add(suiteDO.getSuiteId());
                }
            }
        }
        return result;
    }

    private Map<String,List<Long>> groupSuiteByType(Long villageId){
        Map<String,List<Long>> result = new HashMap<String, List<Long>>();

        BuildingQuery buildingQuery = new BuildingQuery();
        buildingQuery.setVillageId(villageId);
        List<BuildingDO> buildingDOs = buildingDAO.selectForPage(buildingQuery);

        SysVarQuery sysVarQuery = new SysVarQuery();
        sysVarQuery.setVillageId(villageId);
        sysVarQuery.setPageSize(500);
        sysVarQuery.setVarType(SysVarTypeEnum.building.name());
        List<SysVarDO> sysVarDOs = sysVarDAO.selectForView(sysVarQuery);
        Map<Long, SysVarDO> sysVarDOMap = new HashMap<Long, SysVarDO>();
        for (SysVarDO sysVarDO : sysVarDOs) {
            sysVarDOMap.put(sysVarDO.getVarId(), sysVarDO);
        }


        for (BuildingDO buildingDO : buildingDOs) {
            UnitQuery unitQuery = new UnitQuery();
            unitQuery.setPageSize(10000);
            unitQuery.setBuildingId(buildingDO.getBuildingId());
            List<UnitDO> unitDOs = unitDAO.selectForPage(unitQuery);
            List<Long> unitIdList = TransformHelper.transform(unitDOs, new Transform<UnitDO, Long>() {
                @Override
                public Long transform(UnitDO object) {
                    return object.getUnitId();
                }
            });
            if (unitIdList.size() == 0) {
                continue;
            }

            SuiteQuery suiteQuery = new SuiteQuery();
            suiteQuery.setPageSize(10000);
            suiteQuery.setUnitIdList(unitIdList);
            List<SuiteDO> suiteDOs = suiteDAO.selectForPage(suiteQuery);
            List<Long> suiteIdList = TransformHelper.transform(suiteDOs, new Transform<SuiteDO, Long>() {
                @Override
                public Long transform(SuiteDO object) {
                    return object.getUnitId();
                }
            });
            if (suiteIdList.size() == 0) {
                continue;
            }
            for(SuiteDO suiteDO:suiteDOs){
                SysVarDO sysVarDO = sysVarDOMap.get(suiteDO.getBuildingTypeId());
                String groupName;
                if(sysVarDO == null){
                    groupName="未分组";
                }else{
                    groupName = sysVarDO.getVarValue();
                }
                List<Long> longs = result.get(groupName);
                if(longs == null){
                    longs = new ArrayList<Long>();
                    longs.add(suiteDO.getSuiteId());
                    result.put(groupName,longs);
                }else{
                    longs.add(suiteDO.getSuiteId());
                }
            }

        }
        return result;
    }

    private Map<String,List<Long>> groupSuiteByManage(Long villageId){
        Map<String,List<Long>> result = new HashMap<String, List<Long>>();
        OfficeEmployeeQuery officeEmployeeQuery = new OfficeEmployeeQuery();
        officeEmployeeQuery.setVillageId(villageId);
        officeEmployeeQuery.setPageSize(5000);
        List<OfficeEmployeeDO> officeEmployeeDOList = officeEmployeeDAO.selectForPage(officeEmployeeQuery);
        Map<Long, OfficeEmployeeDO> officeEmployeeDOMap = new HashMap<Long, OfficeEmployeeDO>();
        for (OfficeEmployeeDO officeEmployeeDO : officeEmployeeDOList) {
            officeEmployeeDOMap.put(officeEmployeeDO.getEmployeeId(), officeEmployeeDO);
        }
        BuildingQuery buildingQuery = new BuildingQuery();
        buildingQuery.setVillageId(villageId);
        List<BuildingDO> buildingDOs = buildingDAO.selectForPage(buildingQuery);

        List<Long> buildingIdList = TransformHelper.transform(buildingDOs, new Transform<BuildingDO, Long>() {
            @Override
            public Long transform(BuildingDO object) {
                return object.getBuildingId();
            }
        });
        if (buildingIdList.size() == 0) {
            return result;
        }
        for (Long buildingId : buildingIdList) {
            UnitQuery unitQuery = new UnitQuery();
            unitQuery.setPageSize(10000);
            unitQuery.setBuildingId(buildingId);
            List<UnitDO> unitDOs = unitDAO.selectForPage(unitQuery);
            List<Long> unitIdList = TransformHelper.transform(unitDOs, new Transform<UnitDO, Long>() {
                @Override
                public Long transform(UnitDO object) {
                    return object.getUnitId();
                }
            });
            if (unitIdList.size() == 0) {
                continue;
            }

            SuiteQuery suiteQuery = new SuiteQuery();
            suiteQuery.setPageSize(10000);
            suiteQuery.setUnitIdList(unitIdList);
            List<SuiteDO> suiteDOs = suiteDAO.selectForPage(suiteQuery);
            for(SuiteDO suiteDO:suiteDOs){
                OfficeEmployeeDO officeEmployeeDO = officeEmployeeDOMap.get(suiteDO.getEmployeeId());
                String groupName;
                if(officeEmployeeDO == null){
                    groupName="未分组";
                }else{
                    groupName = officeEmployeeDO.getUserName();
                }
                List<Long> longs = result.get(groupName);
                if(longs == null){
                    longs = new ArrayList<Long>();
                    longs.add(suiteDO.getSuiteId());
                    result.put(groupName,longs);
                }else{
                    longs.add(suiteDO.getSuiteId());
                }
            }
        }
        return result;
    }

    private Map<String,List<Long>> groupSuiteByVillage(Long villageId){
        Map<String,List<Long>> result = new HashMap<String, List<Long>>();
        VillageDO villageById = villageDAO.getVillageById(villageId);
        BuildingQuery buildingQuery = new BuildingQuery();
        buildingQuery.setVillageId(villageId);
        List<BuildingDO> buildingDOs = buildingDAO.selectForPage(buildingQuery);

        List<Long> buildingIdList = TransformHelper.transform(buildingDOs, new Transform<BuildingDO, Long>() {
            @Override
            public Long transform(BuildingDO object) {
                return object.getBuildingId();
            }
        });
        if (buildingIdList.size() == 0) {
            return result;
        }
        List<Long> suiteIdList = new ArrayList<Long>();
        for (Long buildingId : buildingIdList) {
            UnitQuery unitQuery = new UnitQuery();
            unitQuery.setPageSize(10000);
            unitQuery.setBuildingId(buildingId);
            List<UnitDO> unitDOs = unitDAO.selectForPage(unitQuery);
            List<Long> unitIdList = TransformHelper.transform(unitDOs, new Transform<UnitDO, Long>() {
                @Override
                public Long transform(UnitDO object) {
                    return object.getUnitId();
                }
            });
            if (unitIdList.size() == 0) {
                continue;
            }

            SuiteQuery suiteQuery = new SuiteQuery();
            suiteQuery.setPageSize(10000);
            suiteQuery.setUnitIdList(unitIdList);
            List<SuiteDO> suiteDOs = suiteDAO.selectForPage(suiteQuery);
            for(SuiteDO suiteDO:suiteDOs){
                suiteIdList.add(suiteDO.getSuiteId());
            }
        }
        result.put(villageById.getVillageName(), suiteIdList);
        return result;
    }



    @Override
    public BizResult statTieOff(StatFeeForm statFeeForm) {
        BizResult bizResult = new BizResult();

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date startDate = null;
        Date endDate = null;
        try {
            startDate = simpleDateFormat.parse(statFeeForm.getStartDate());
            endDate = simpleDateFormat.parse(statFeeForm.getEndDate());
            if (startDate.after(endDate)) {
                Date temp = startDate;
                startDate = endDate;
                endDate = temp;
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(startDate);
        startCalendar.add(Calendar.DAY_OF_YEAR, -1);
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(endDate);

        //int startDay = startCalendar.get(Calendar.DAY_OF_YEAR);
        //int endDay = endCalendar.get(Calendar.DAY_OF_YEAR) + 1;

        BuildingQuery buildingQuery = new BuildingQuery();
        buildingQuery.setPageSize(10000);
        buildingQuery.setVillageId(statFeeForm.getVillageId());
        List<BuildingDO> buildingDOs = buildingDAO.selectForPage(buildingQuery);
        List<Long> buildingIdList = TransformHelper.transform(buildingDOs, new Transform<BuildingDO, Long>() {
            @Override
            public Long transform(BuildingDO object) {
                return object.getBuildingId();
            }
        });
        if (buildingIdList.size() == 0) {
            return null;
        }

        UnitQuery unitQuery = new UnitQuery();
        unitQuery.setPageSize(10000);
        unitQuery.setBuildingIdList(buildingIdList);
        List<UnitDO> unitDOs = unitDAO.selectForPage(unitQuery);
        List<Long> unitIdList = TransformHelper.transform(unitDOs, new Transform<UnitDO, Long>() {
            @Override
            public Long transform(UnitDO object) {
                return object.getUnitId();
            }
        });
        if (unitIdList.size() == 0) {
            return null;
        }

        SuiteQuery suiteQuery = new SuiteQuery();
        suiteQuery.setPageSize(10000);
        suiteQuery.setUnitIdList(unitIdList);
        List<SuiteDO> suiteDOs = suiteDAO.selectForPage(suiteQuery);
        List<Long> suiteIdList = TransformHelper.transform(suiteDOs, new Transform<SuiteDO, Long>() {
            @Override
            public Long transform(SuiteDO object) {
                return object.getSuiteId();
            }
        });
        List<Long> waterMeterSuiteIdList = new ArrayList<Long>();
        List<Long> waterIcSuiteIdList = new ArrayList<Long>();
        List<Long> elecMeterSuiteIdList = new ArrayList<Long>();
        List<Long> elecIcSuiteIdList = new ArrayList<Long>();
        for (SuiteDO suiteDO : suiteDOs) {
            if (suiteDO.getTypeWater().equals(MeterTypeEnum.meter.getDesc())) {
                waterMeterSuiteIdList.add(suiteDO.getSuiteId());
            } else {
                waterIcSuiteIdList.add(suiteDO.getSuiteId());
            }
            if (suiteDO.getTypeElectrical().equals(MeterTypeEnum.meter.getDesc())) {
                elecMeterSuiteIdList.add(suiteDO.getSuiteId());
            }else if(suiteDO.getTypeElectrical().equals(MeterTypeEnum.gate.getDesc())){
                //TODO
            } else {
                elecIcSuiteIdList.add(suiteDO.getSuiteId());
            }
        }

        ParkingQuery parkingQuery = new ParkingQuery();
        parkingQuery.setVillageId(statFeeForm.getVillageId());
        parkingQuery.setPageSize(10000);
        List<ParkingDO> parkingDOs = parkingDAO.selectForPage(parkingQuery);
        List<Long> parkingIdList = TransformHelper.transform(parkingDOs, new Transform<ParkingDO, Long>() {
            @Override
            public Long transform(ParkingDO object) {
                return object.getParkingId();
            }
        });

        SysVarQuery sysVarQuery = new SysVarQuery();
        sysVarQuery.setVillageId(statFeeForm.getVillageId());
        sysVarQuery.setVarType(SysVarTypeEnum.deposit.name());
        sysVarQuery.setPageSize(500);
        List<SysVarDO> depositSysVarDOs = sysVarDAO.selectForPage(sysVarQuery);
        Set<Long> depositVarIdSet = TransformHelper.transform2Set(depositSysVarDOs, new Transform<SysVarDO, Long>() {
            @Override
            public Long transform(SysVarDO object) {
                return object.getVarId();
            }
        });

        sysVarQuery.setVarType(SysVarTypeEnum.ext.name());
        sysVarQuery.setPageSize(500);
        List<SysVarDO> extSysVarDOs = sysVarDAO.selectForPage(sysVarQuery);

        //临时费用
        sysVarQuery.setVarType(SysVarTypeEnum.extra_fee.name());
        List<SysVarDO> extraSysVarDOs = sysVarDAO.selectForPage(sysVarQuery);
        bizResult.data.put("extraList", extraSysVarDOs);
        Map<String, List<Long>> extVarMap = new LinkedHashMap<String, List<Long>>();
        for (SysVarDO sysVarDO : extSysVarDOs) {
            List<Long> longs = extVarMap.get(sysVarDO.getVarValue());
            if (longs == null) {
                longs = new ArrayList<Long>();
                longs.add(sysVarDO.getVarId());
                extVarMap.put(sysVarDO.getVarValue(), longs);
            } else {
                longs.add(sysVarDO.getVarId());
            }
        }
        List<Long> depositVarIdList = new ArrayList<Long>(depositVarIdSet);
        // List<Long> extVarIdList = new ArrayList<Long>(extVarIdSet);
        Map<String, BillStatVO> map = new LinkedHashMap<String, BillStatVO>();
        while (startCalendar.before(endCalendar)) {
            startCalendar.add(Calendar.DAY_OF_MONTH, 1);
            Date stat = startCalendar.getTime();
            SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd");
            BillStatVO billStatVO = statBillWithRefund(stat, suiteIdList, parkingIdList, depositVarIdList, waterMeterSuiteIdList, waterIcSuiteIdList,
                    elecMeterSuiteIdList, elecIcSuiteIdList,
                    extVarMap, extraSysVarDOs);

            map.put(simpleDateFormat1.format(stat), billStatVO);

            long feeTotal = 0;
            feeTotal = feeTotal + billStatVO.getElecICPayTotal() + billStatVO.getElecMeterPayTotal() + billStatVO.getWaterICPayTotal() + billStatVO.getWaterMeterPayTotal()
                    + billStatVO.getEstatePayTotal() + billStatVO.getParkingPayTotal() + billStatVO.getExtPayTotal();
            if (billStatVO.getStatObjList() != null) {
                for (StatObj statObj : billStatVO.getStatObjList()) {
                    feeTotal = feeTotal + statObj.getFeeTotal();
                }
            }
            if (billStatVO.getExtraObjList() != null) {
                for (StatObj statObj : billStatVO.getExtraObjList()) {
                    feeTotal = feeTotal + statObj.getFeeTotal();
                }
            }
            billStatVO.setFeeTotal(feeTotal);
        }
        bizResult.data.put("statMap", map);
        bizResult.data.put("extList", new ArrayList(extVarMap.keySet()));

        List<String> accountEstateTypeList = new ArrayList<String>();
        accountEstateTypeList.add(AccountEstateTypeEnum.bank.getDesc());
        accountEstateTypeList.add(AccountEstateTypeEnum.transfer.getDesc());
        accountEstateTypeList.add(AccountEstateTypeEnum.card.getDesc());
        accountEstateTypeList.add(AccountEstateTypeEnum.weixin.getDesc());
        bizResult.data.put("accountEstateTypeList", accountEstateTypeList);
        //合计


        bizResult.success = true;
        return bizResult;
    }

    @Override
    public BizResult statEstateLastYear(StatFeeForm statFeeForm) {
        BizResult bizResult = new BizResult();
        if (statFeeForm.getVillageId() != null) {
            SysVarQuery sysVarQuery = new SysVarQuery();
            sysVarQuery.setVillageId(statFeeForm.getVillageId());
            sysVarQuery.setVarType(SysVarTypeEnum.building.name());
            sysVarQuery.setPageSize(500);
            List<SysVarDO> sysVarDOs = sysVarDAO.selectForPage(sysVarQuery);
            bizResult.data.put("buildingTypeList", sysVarDOs);
        }
        List<Long> suiteIdList = getSuiteIdList(statFeeForm);
        if (suiteIdList == null || suiteIdList.size() == 0) {
            bizResult.success = true;
            return bizResult;
        }

        Date startDate = null;
        Date endDate = null;
        if (statFeeForm.getStartDate() != null) {
            String start = statFeeForm.getStartDate() + "-01 00:00:00";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                startDate = simpleDateFormat.parse(start);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        if (statFeeForm.getEndDate() != null) {
            String end = statFeeForm.getEndDate() + "-01 00:00:00";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                Date parse = simpleDateFormat.parse(end);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(parse);
                calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
                calendar.set(Calendar.HOUR_OF_DAY, 23);
                calendar.set(Calendar.MINUTE, 59);
                calendar.set(Calendar.SECOND, 59);
                endDate = (calendar.getTime());
            } catch (ParseException e) {
                e.printStackTrace();
            }

        }


        List<BillEstateDO> bill = billEstateDAO.statLastBill(suiteIdList, startDate, null);
        Set<Long> suiteIdSet = TransformHelper.transform2Set(bill, new Transform<BillEstateDO, Long>() {
            @Override
            public Long transform(BillEstateDO object) {
                return object.getSuiteId();
            }
        });
        if (suiteIdSet.size() == 0) {
            bizResult.success = true;
            return bizResult;
        }
        List<SuiteDO> suiteByIds = suiteDAO.getSuiteByIds(new ArrayList(suiteIdSet));
        Map<Long, SuiteDO> suiteDOMap = new HashMap<Long, SuiteDO>();
        for (SuiteDO suiteDO : suiteByIds) {
            suiteDOMap.put(suiteDO.getSuiteId(), suiteDO);
        }


        if (StatTypeEnum.office.name().equals(statFeeForm.getType())) {
            SysVarQuery sysVarQuery = new SysVarQuery();
            sysVarQuery.setPageSize(500);
            sysVarQuery.setVillageId(statFeeForm.getVillageId());
            sysVarQuery.setVarType(SysVarTypeEnum.office.name());
            List<SysVarDO> sysVarDOs = sysVarDAO.selectForView(sysVarQuery);
            Map<Long, SysVarDO> sysVarDOMap = new HashMap<Long, SysVarDO>();
            for (SysVarDO sysVarDO : sysVarDOs) {
                sysVarDOMap.put(sysVarDO.getVarId(), sysVarDO);
            }
            Map<Long, List<BillEstateDO>> billMap = new HashMap<Long, List<BillEstateDO>>();
            for (BillEstateDO billEstateDO : bill) {
                SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
                List<BillEstateDO> billEstateDOList = billMap.get(suiteDO.getOfficeVarId());
                if (billEstateDOList == null) {
                    billEstateDOList = new ArrayList<BillEstateDO>();
                    billEstateDOList.add(billEstateDO);
                    billMap.put(suiteDO.getOfficeVarId(), billEstateDOList);
                } else {
                    billEstateDOList.add(billEstateDO);
                }
            }
            Map<String, BillLastYearRateVO> billLastYearRateVOMap = new HashMap<String, BillLastYearRateVO>();
            Iterator<Map.Entry<Long, List<BillEstateDO>>> iterator = billMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<Long, List<BillEstateDO>> next = iterator.next();
                Long varId = next.getKey();
                List<BillEstateDO> estateDOList = next.getValue();
                SysVarDO sysVarDO = sysVarDOMap.get(varId);
                String groupName;
                if (sysVarDO == null) {
                    groupName = "未分类";
                } else {
                    groupName = sysVarDO.getVarValue();
                }
                long unpay = 0;
                long pay = 0;
                for (BillEstateDO billEstateDO : estateDOList) {
                    if (billEstateDO.getIsPayed() != null && billEstateDO.getIsPayed().intValue() == 1) {
                        pay += billEstateDO.getPayTotal();
                    } else {
                        unpay += billEstateDO.getPayTotal();
                    }
                }
                BillLastYearRateVO billLastYearRateVO = new BillLastYearRateVO();
                billLastYearRateVO.setPayedTotalLastYear(pay);
                billLastYearRateVO.setUnpayTotalLastYear(unpay);
                billLastYearRateVO.setRateLastYear(getRate(pay, pay + unpay));
                billLastYearRateVOMap.put(groupName, billLastYearRateVO);
            }
            bizResult.data.put("billLastYearRateVOMap", billLastYearRateVOMap);
        } else if (StatTypeEnum.type.name().equals(statFeeForm.getType())) {

            BuildingQuery buildingQuery = new BuildingQuery();
            buildingQuery.setVillageId(statFeeForm.getVillageId());
            List<BuildingDO> buildingDOs = buildingDAO.selectForPage(buildingQuery);
            Map<Long, BuildingDO> buildingDOMap = new HashMap<Long, BuildingDO>();
            for (BuildingDO buildingDO : buildingDOs) {
                buildingDOMap.put(buildingDO.getBuildingId(), buildingDO);
            }

            List<Long> buildingIdList = TransformHelper.transform(buildingDOs, new Transform<BuildingDO, Long>() {
                @Override
                public Long transform(BuildingDO object) {
                    return object.getBuildingId();
                }
            });
            if (buildingIdList.size() == 0) {
                bizResult.success = true;
                return bizResult;
            }

            Map<Long, Long> buildingSuiteMap = new HashMap<Long, Long>();
            for (Long buildingId : buildingIdList) {
                UnitQuery unitQuery = new UnitQuery();
                unitQuery.setPageSize(10000);
                unitQuery.setBuildingId(buildingId);
                List<UnitDO> unitDOs = unitDAO.selectForPage(unitQuery);
                List<Long> unitIdList = TransformHelper.transform(unitDOs, new Transform<UnitDO, Long>() {
                    @Override
                    public Long transform(UnitDO object) {
                        return object.getUnitId();
                    }
                });
                if (unitIdList.size() == 0) {
                    continue;
                }

                SuiteQuery suiteQuery = new SuiteQuery();
                suiteQuery.setPageSize(10000);
                suiteQuery.setUnitIdList(unitIdList);
                List<SuiteDO> suiteDOs = suiteDAO.selectForPage(suiteQuery);
                for (SuiteDO suiteDO : suiteDOs) {
                    buildingSuiteMap.put(suiteDO.getSuiteId(), buildingId);
                }
            }
            SysVarQuery sysVarQuery = new SysVarQuery();
            sysVarQuery.setPageSize(500);
            sysVarQuery.setVillageId(statFeeForm.getVillageId());
            sysVarQuery.setVarType(SysVarTypeEnum.building.name());
            List<SysVarDO> sysVarDOs = sysVarDAO.selectForView(sysVarQuery);
            Map<Long, SysVarDO> sysVarDOMap = new HashMap<Long, SysVarDO>();
            for (SysVarDO sysVarDO : sysVarDOs) {
                sysVarDOMap.put(sysVarDO.getVarId(), sysVarDO);
            }

            Map<Long, List<BillEstateDO>> billMap = new HashMap<Long, List<BillEstateDO>>();
            for (BillEstateDO billEstateDO : bill) {
                SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
                //Long buildingId = buildingSuiteMap.get(billEstateDO.getSuiteId());
                //BuildingDO buildingDO = buildingDOMap.get(buildingId);
                List<BillEstateDO> billEstateDOList = billMap.get(suiteDO.getBuildingTypeId());
                if (billEstateDOList == null) {
                    billEstateDOList = new ArrayList<BillEstateDO>();
                    billEstateDOList.add(billEstateDO);
                    billMap.put(suiteDO.getBuildingTypeId(), billEstateDOList);
                } else {
                    billEstateDOList.add(billEstateDO);
                }
            }
            Map<String, BillLastYearRateVO> billLastYearRateVOMap = new HashMap<String, BillLastYearRateVO>();
            Iterator<Map.Entry<Long, List<BillEstateDO>>> iterator = billMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<Long, List<BillEstateDO>> next = iterator.next();
                Long varId = next.getKey();
                List<BillEstateDO> estateDOList = next.getValue();
                SysVarDO sysVarDO = sysVarDOMap.get(varId);
                String groupName;
                if (sysVarDO == null) {
                    groupName = "未分类";
                } else {
                    groupName = sysVarDO.getVarValue();
                }
                long unpay = 0;
                long pay = 0;
                for (BillEstateDO billEstateDO : estateDOList) {
                    if (billEstateDO.getIsPayed() != null && billEstateDO.getIsPayed().intValue() == 1) {
                        pay += billEstateDO.getPayTotal();
                    } else {
                        unpay += billEstateDO.getPayTotal();
                    }
                }
                BillLastYearRateVO billLastYearRateVO = new BillLastYearRateVO();
                billLastYearRateVO.setPayedTotalLastYear(pay);
                billLastYearRateVO.setUnpayTotalLastYear(unpay);
                billLastYearRateVO.setRateLastYear(getRate(pay, pay + unpay));
                billLastYearRateVOMap.put(groupName, billLastYearRateVO);
            }
            bizResult.data.put("billLastYearRateVOMap", billLastYearRateVOMap);

        } else if (StatTypeEnum.manage.name().equals(statFeeForm.getType())) {
            OfficeEmployeeQuery officeEmployeeQuery = new OfficeEmployeeQuery();
            officeEmployeeQuery.setVillageId(statFeeForm.getVillageId());
            officeEmployeeQuery.setPageSize(5000);
            List<OfficeEmployeeDO> officeEmployeeDOList = officeEmployeeDAO.selectForPage(officeEmployeeQuery);
            Map<Long, OfficeEmployeeDO> officeEmployeeDOMap = new HashMap<Long, OfficeEmployeeDO>();
            for (OfficeEmployeeDO officeEmployeeDO : officeEmployeeDOList) {
                officeEmployeeDOMap.put(officeEmployeeDO.getEmployeeId(), officeEmployeeDO);
            }
            Map<Long, List<BillEstateDO>> billMap = new HashMap<Long, List<BillEstateDO>>();
            for (BillEstateDO billEstateDO : bill) {
                SuiteDO suiteDO = suiteDOMap.get(billEstateDO.getSuiteId());
                List<BillEstateDO> billEstateDOList = billMap.get(suiteDO.getEmployeeId());
                if (billEstateDOList == null) {
                    billEstateDOList = new ArrayList<BillEstateDO>();
                    billEstateDOList.add(billEstateDO);
                    billMap.put(suiteDO.getEmployeeId(), billEstateDOList);
                } else {
                    billEstateDOList.add(billEstateDO);
                }
            }
            Map<String, BillLastYearRateVO> billLastYearRateVOMap = new HashMap<String, BillLastYearRateVO>();
            Iterator<Map.Entry<Long, List<BillEstateDO>>> iterator = billMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<Long, List<BillEstateDO>> next = iterator.next();
                Long varId = next.getKey();
                List<BillEstateDO> estateDOList = next.getValue();
                OfficeEmployeeDO officeEmployeeDO = officeEmployeeDOMap.get(varId);
                String groupName;
                if (officeEmployeeDO == null) {
                    groupName = "未分类";
                } else {
                    groupName = officeEmployeeDO.getUserName();
                }
                long unpay = 0;
                long pay = 0;
                for (BillEstateDO billEstateDO : estateDOList) {
                    if (billEstateDO.getIsPayed() != null && billEstateDO.getIsPayed().intValue() == 1) {
                        pay += billEstateDO.getPayTotal();
                    } else {
                        unpay += billEstateDO.getPayTotal();
                    }
                }
                BillLastYearRateVO billLastYearRateVO = new BillLastYearRateVO();
                billLastYearRateVO.setPayedTotalLastYear(pay);
                billLastYearRateVO.setUnpayTotalLastYear(unpay);
                billLastYearRateVO.setRateLastYear(getRate(pay, pay + unpay));
                billLastYearRateVOMap.put(groupName, billLastYearRateVO);
            }
            bizResult.data.put("billLastYearRateVOMap", billLastYearRateVOMap);

        } else if (StatTypeEnum.village.name().equals(statFeeForm.getType())) {
            Map<String, BillLastYearRateVO> billLastYearRateVOMap = new HashMap<String, BillLastYearRateVO>();
            long unpay = 0;
            long pay = 0;
            for (BillEstateDO billEstateDO : bill) {
                if (billEstateDO.getIsPayed() != null && billEstateDO.getIsPayed().intValue() == 1) {
                    pay += billEstateDO.getPayTotal();
                } else {
                    unpay += billEstateDO.getPayTotal();
                }
            }
            VillageDO villageById = villageDAO.getVillageById(statFeeForm.getVillageId());
            BillLastYearRateVO billLastYearRateVO = new BillLastYearRateVO();
            billLastYearRateVO.setPayedTotalLastYear(pay);
            billLastYearRateVO.setUnpayTotalLastYear(unpay);
            billLastYearRateVO.setRateLastYear(getRate(pay, pay + unpay));
            billLastYearRateVOMap.put(villageById.getVillageName(), billLastYearRateVO);
            bizResult.data.put("billLastYearRateVOMap", billLastYearRateVOMap);
        } else if (StatTypeEnum.building.name().equals(statFeeForm.getType())) {
            BuildingQuery buildingQuery = new BuildingQuery();
            buildingQuery.setVillageId(statFeeForm.getVillageId());
            List<BuildingDO> buildingDOs = buildingDAO.selectForPage(buildingQuery);
            Map<Long, BuildingDO> buildingDOMap = new HashMap<Long, BuildingDO>();
            for (BuildingDO buildingDO : buildingDOs) {
                buildingDOMap.put(buildingDO.getBuildingId(), buildingDO);
            }

            List<Long> buildingIdList = TransformHelper.transform(buildingDOs, new Transform<BuildingDO, Long>() {
                @Override
                public Long transform(BuildingDO object) {
                    return object.getBuildingId();
                }
            });
            if (buildingIdList.size() == 0) {
                bizResult.success = true;
                return bizResult;
            }

            Map<Long, Long> buildingSuiteMap = new HashMap<Long, Long>();
            for (Long buildingId : buildingIdList) {
                UnitQuery unitQuery = new UnitQuery();
                unitQuery.setPageSize(10000);
                unitQuery.setBuildingId(buildingId);
                List<UnitDO> unitDOs = unitDAO.selectForPage(unitQuery);
                List<Long> unitIdList = TransformHelper.transform(unitDOs, new Transform<UnitDO, Long>() {
                    @Override
                    public Long transform(UnitDO object) {
                        return object.getUnitId();
                    }
                });
                if (unitIdList.size() == 0) {
                    continue;
                }

                SuiteQuery suiteQuery = new SuiteQuery();
                suiteQuery.setPageSize(10000);
                suiteQuery.setUnitIdList(unitIdList);
                List<SuiteDO> suiteDOs = suiteDAO.selectForPage(suiteQuery);
                for (SuiteDO suiteDO : suiteDOs) {
                    buildingSuiteMap.put(suiteDO.getSuiteId(), buildingId);
                }
            }

            Map<Long, List<BillEstateDO>> billMap = new HashMap<Long, List<BillEstateDO>>();
            for (BillEstateDO billEstateDO : bill) {
                Long buildingId = buildingSuiteMap.get(billEstateDO.getSuiteId());
                BuildingDO buildingDO = buildingDOMap.get(buildingId);
                List<BillEstateDO> billEstateDOList = billMap.get(buildingDO.getBuildingId());
                if (billEstateDOList == null) {
                    billEstateDOList = new ArrayList<BillEstateDO>();
                    billEstateDOList.add(billEstateDO);
                    billMap.put(buildingDO.getBuildingId(), billEstateDOList);
                } else {
                    billEstateDOList.add(billEstateDO);
                }
            }
            Map<String, BillLastYearRateVO> billLastYearRateVOMap = new HashMap<String, BillLastYearRateVO>();
            Iterator<Map.Entry<Long, List<BillEstateDO>>> iterator = billMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<Long, List<BillEstateDO>> next = iterator.next();
                Long varId = next.getKey();
                List<BillEstateDO> estateDOList = next.getValue();
                BuildingDO buildingDO = buildingDOMap.get(varId);
                String groupName;
                if (buildingDO == null) {
                    groupName = "未分类";
                } else {
                    groupName = buildingDO.getBuildingName();
                }
                long unpay = 0;
                long pay = 0;
                for (BillEstateDO billEstateDO : estateDOList) {
                    if (billEstateDO.getIsPayed() != null && billEstateDO.getIsPayed().intValue() == 1) {
                        pay += billEstateDO.getPayTotal();
                    } else {
                        unpay += billEstateDO.getPayTotal();
                    }
                }
                BillLastYearRateVO billLastYearRateVO = new BillLastYearRateVO();
                billLastYearRateVO.setPayedTotalLastYear(pay);
                billLastYearRateVO.setUnpayTotalLastYear(unpay);
                billLastYearRateVO.setRateLastYear(getRate(pay, pay + unpay));
                billLastYearRateVOMap.put(groupName, billLastYearRateVO);
            }
            bizResult.data.put("billLastYearRateVOMap", billLastYearRateVOMap);
        }

        bizResult.success = true;
        return bizResult;
    }

    @Override
    public BizResult statWaterElec(StatFeeForm statFeeForm) {
        BizResult bizResult  = new BizResult();

        if (statFeeForm.getVillageId() != null) {
            SysVarQuery sysVarQuery = new SysVarQuery();
            sysVarQuery.setVillageId(statFeeForm.getVillageId());
            sysVarQuery.setVarType(SysVarTypeEnum.building.name());
            sysVarQuery.setPageSize(500);
            List<SysVarDO> sysVarDOs = sysVarDAO.selectForPage(sysVarQuery);
            bizResult.data.put("buildingTypeList", sysVarDOs);
        }
        List<Long> suiteIdList = getSuiteIdList(statFeeForm);
        if (suiteIdList == null || suiteIdList.size() == 0) {
            bizResult.success = true;
            return bizResult;
        }


        Date startDate = null;
        Date endDate = null;
        if (StringUtils.hasText(statFeeForm.getStartDate())) {
            String start = statFeeForm.getStartDate() + "-01 00:00:00";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                startDate = simpleDateFormat.parse(start);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        if (StringUtils.hasText(statFeeForm.getEndDate() )) {
            String end = statFeeForm.getEndDate() + "-01 00:00:00";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                Date parse = simpleDateFormat.parse(end);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(parse);
                calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
                calendar.set(Calendar.HOUR_OF_DAY, 23);
                calendar.set(Calendar.MINUTE, 59);
                calendar.set(Calendar.SECOND, 59);
                endDate = (calendar.getTime());
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        List<BillWaterDO> billWater = billWaterDAO.getBillList(suiteIdList, startDate, endDate, null);
        Set<Long> suiteIdSet = TransformHelper.transform2Set(billWater, new Transform<BillWaterDO, Long>() {
            @Override
            public Long transform(BillWaterDO object) {
                return object.getSuiteId();
            }
        });
        List<BillElecDO> billElec = billElecDAO.getBillList(suiteIdList, startDate, endDate, null);
        Set<Long> suiteIdSetByElec = TransformHelper.transform2Set(billElec, new Transform<BillElecDO, Long>() {
            @Override
            public Long transform(BillElecDO object) {
                return object.getSuiteId();
            }
        });
        suiteIdSet.addAll(suiteIdSetByElec);

        if (suiteIdSet.size() == 0) {
            bizResult.success = true;
            return bizResult;
        }
        List<SuiteDO> suiteByIds = suiteDAO.getSuiteByIds(new ArrayList(suiteIdSet));
        Map<Long, SuiteDO> suiteDOMap = new HashMap<Long, SuiteDO>();
        for (SuiteDO suiteDO : suiteByIds) {
            suiteDOMap.put(suiteDO.getSuiteId(), suiteDO);
        }

        List<BillWaterElecVO> waterElecBillList = new ArrayList<BillWaterElecVO>(billWater.size()+billElec.size());
        for(BillElecDO billElecDO:billElec){
            waterElecBillList.add(new BillWaterElecVO(billElecDO));
        }
        for(BillWaterDO billWaterDO:billWater){
            waterElecBillList.add(new BillWaterElecVO(billWaterDO));
        }

        if (StatTypeEnum.office.name().equals(statFeeForm.getType())) {
            statWaterElecByOffice(bizResult, waterElecBillList, suiteDOMap
                    , statFeeForm, startDate, endDate, suiteIdList);
        } else if (StatTypeEnum.type.name().equals(statFeeForm.getType())) {
            statWaterElecByBuildingType(bizResult, waterElecBillList, suiteDOMap
                    , statFeeForm, startDate, endDate, suiteIdList);
        } else if (StatTypeEnum.manage.name().equals(statFeeForm.getType())) {
            statWaterElecByManage(bizResult, waterElecBillList, suiteDOMap
                    , statFeeForm, startDate, endDate, suiteIdList);
        } else if (StatTypeEnum.village.name().equals(statFeeForm.getType())) {
            statWaterElecByVillage(bizResult, waterElecBillList, suiteDOMap
                    , statFeeForm, startDate, endDate, suiteIdList);
        } else if (StatTypeEnum.building.name().equals(statFeeForm.getType())) {
            statWaterElecByBuilding(bizResult, waterElecBillList, suiteDOMap
                    , statFeeForm, startDate, endDate, suiteIdList);
        }


        bizResult.success = true;
        return bizResult;
    }

    @Override
    public BizResult estateRateCompare(StatFeeForm statFeeForm) {

        BizResult bizResult = new BizResult();
        if (statFeeForm.getVillageId() == null) {
            bizResult.success = true;
            return bizResult;
        }
        Map<String,List<Long>> group = new HashMap<String, List<Long>>();
        if (StatTypeEnum.office.name().equals(statFeeForm.getType())) {
            group = groupSuiteByOffice(statFeeForm.getVillageId());
        } else if (StatTypeEnum.type.name().equals(statFeeForm.getType())) {
            group = groupSuiteByType(statFeeForm.getVillageId());
        } else if (StatTypeEnum.manage.name().equals(statFeeForm.getType())) {
            group = groupSuiteByManage(statFeeForm.getVillageId());
        } else if (StatTypeEnum.village.name().equals(statFeeForm.getType())) {
            group = groupSuiteByVillage(statFeeForm.getVillageId());
        } else if (StatTypeEnum.building.name().equals(statFeeForm.getType())) {
            group = groupSuiteByBuilding(statFeeForm.getVillageId());
        }

        Date startDate = null;
        Date endDate = null;
        Date startDateLast = null;
        Date endDateLast = null;
        if (statFeeForm.getStartDate() != null) {
            String start = statFeeForm.getStartDate() + "-01 00:00:00";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                startDate = simpleDateFormat.parse(start);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(startDate);
                calendar.add(Calendar.YEAR,-1);
                startDateLast  = calendar.getTime();
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        if (statFeeForm.getEndDate() != null) {
            String end = statFeeForm.getEndDate() + "-01 00:00:00";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                Date parse = simpleDateFormat.parse(end);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(parse);
                calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
                calendar.set(Calendar.HOUR_OF_DAY, 23);
                calendar.set(Calendar.MINUTE, 59);
                calendar.set(Calendar.SECOND, 59);
                endDate = (calendar.getTime());
                calendar.add(Calendar.YEAR,-1);
                endDateLast  = calendar.getTime();
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        Map<String,EstateRateCompareVO> result = new HashMap<String, EstateRateCompareVO>();

        Iterator<Map.Entry<String, List<Long>>> iterator = group.entrySet().iterator();
        while(iterator.hasNext()) {
            Map.Entry<String, List<Long>> next = iterator.next();
            List<Long> suiteIdList = next.getValue();
            EstateRateCompareVO estateRateCompareVO = new EstateRateCompareVO();
            if (suiteIdList.size() > 0) {
                List<BillEstateDO> billEstateDOList = billEstateDAO.getBill(suiteIdList, startDate, endDate, null);
                long receivableNow = 0;
                long paidNow = 0;
                for(BillEstateDO billEstateDO:billEstateDOList){
                    receivableNow+=billEstateDO.getPayTotal();
                    if(billEstateDO.getIsPayed().intValue() == 1){
                        paidNow+=billEstateDO.getPayTotal();
                    }
                }
                estateRateCompareVO.setPaidNow(paidNow);
                estateRateCompareVO.setReceivableNow(receivableNow);
                estateRateCompareVO.setRateNow(getRate(paidNow,receivableNow));

                List<BillEstateDO> billEstateDOListLast = billEstateDAO.getBill(suiteIdList, startDateLast, endDateLast, null);
                long receivableLast = 0;
                long paidLast = 0;
                for(BillEstateDO billEstateDO:billEstateDOListLast){
                    receivableLast+=billEstateDO.getPayTotal();
                    if(billEstateDO.getIsPayed().intValue() == 1){
                        paidLast+=billEstateDO.getPayTotal();
                    }
                }
                estateRateCompareVO.setPaidLastYear(paidLast);
                estateRateCompareVO.setReceivableLastYear(receivableLast);
                estateRateCompareVO.setRateLastYear(getRate(paidLast, receivableLast));
                if(receivableNow > receivableLast) {
                    estateRateCompareVO.setReceivableDiff(receivableNow - receivableLast);
                }else{
                    estateRateCompareVO.setReceivableDiff(receivableLast - receivableNow);
                }

                if(paidNow > paidLast) {
                    estateRateCompareVO.setPaidDiff(paidNow - paidLast);
                }else{
                    estateRateCompareVO.setPaidDiff(paidLast - paidNow);
                }
            }
            result.put(next.getKey(),estateRateCompareVO);
        }
        bizResult.data.put("map",result);
        bizResult.success=true;
        return bizResult;
    }


    private void statWaterElecByOffice(BizResult bizResult, List<BillWaterElecVO> bill,
                                       Map<Long, SuiteDO> suiteDOMap, StatFeeForm statFeeForm, Date startDate, Date endDate, List<Long> suiteIdList) {
        //按办公室分组
        Map<Long, List<BillWaterElecVO>> billMap = new HashMap<Long, List<BillWaterElecVO>>();
        for (BillWaterElecVO billWaterElecVO : bill) {
            SuiteDO suiteDO = suiteDOMap.get(billWaterElecVO.getSuiteId());
            List<BillWaterElecVO> billWaterElecVOList = billMap.get(suiteDO.getOfficeVarId());
            if (billWaterElecVOList == null) {
                billWaterElecVOList = new ArrayList<BillWaterElecVO>();
                billWaterElecVOList.add(billWaterElecVO);
                billMap.put(suiteDO.getOfficeVarId(), billWaterElecVOList);
            } else {
                billWaterElecVOList.add(billWaterElecVO);
            }
        }
        SysVarQuery sysVarQuery = new SysVarQuery();
        sysVarQuery.setPageSize(500);
        sysVarQuery.setVillageId(statFeeForm.getVillageId());
        sysVarQuery.setVarType(SysVarTypeEnum.office.name());
        List<SysVarDO> sysVarDOs = sysVarDAO.selectForView(sysVarQuery);
        Map<Long, SysVarDO> sysVarDOMap = new HashMap<Long, SysVarDO>();
        for (SysVarDO sysVarDO : sysVarDOs) {
            sysVarDOMap.put(sysVarDO.getVarId(), sysVarDO);
        }
        Map<String, BillRateVO> billRateVOMap = new HashMap<String, BillRateVO>();
        Iterator<Map.Entry<Long, List<BillWaterElecVO>>> iterator = billMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Long, List<BillWaterElecVO>> next = iterator.next();
            Long varId = next.getKey();
            List<BillWaterElecVO> billWaterElecVOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String officeName = "未分类";
            if (sysVarDO != null) {
                officeName = sysVarDO.getVarValue();
            }
            BillRateVO billRateVO = statWaterElecRate(billWaterElecVOList);
            billRateVOMap.put(officeName, billRateVO);
        }

        bizResult.data.put("billRateVOMap", billRateVOMap);
        //统计历年欠费
        List<BillWaterDO> unpayBillWater = billWaterDAO.getBillList(suiteIdList, null, startDate, 0);
        List<BillElecDO> unpayBillElec = billElecDAO.getBillList(suiteIdList, null, startDate, 0);
        List<BillWaterElecVO> waterElecVOList = new ArrayList<BillWaterElecVO>(unpayBillWater.size()+unpayBillElec.size());
        for(BillElecDO billElecDO:unpayBillElec){
            waterElecVOList.add(new BillWaterElecVO(billElecDO));
        }
        for(BillWaterDO billWaterDO:unpayBillWater){
            waterElecVOList.add(new BillWaterElecVO(billWaterDO));
        }
        Map<Long, List<BillWaterElecVO>> unpayBillMap = new HashMap<Long, List<BillWaterElecVO>>();
        for (BillWaterElecVO billWaterElecVO : waterElecVOList) {
            SuiteDO suiteDO = suiteDOMap.get(billWaterElecVO.getSuiteId());
            List<BillWaterElecVO> billDOList = unpayBillMap.get(suiteDO.getOfficeVarId());
            if (billDOList == null) {
                billDOList = new ArrayList<BillWaterElecVO>();
                billDOList.add(billWaterElecVO);
                unpayBillMap.put(suiteDO.getOfficeVarId(), billDOList);
            } else {
                billDOList.add(billWaterElecVO);
            }
        }
        Iterator<Map.Entry<Long, List<BillWaterElecVO>>> unpayIterator = unpayBillMap.entrySet().iterator();
        while (unpayIterator.hasNext()) {
            Map.Entry<Long, List<BillWaterElecVO>> next = unpayIterator.next();
            Long varId = next.getKey();
            List<BillWaterElecVO> doList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String officeName = "未分类";
            if (sysVarDO != null) {
                officeName = sysVarDO.getVarValue();
            }
            long fee = 0;
            for (BillWaterElecVO billWaterElecVO : doList) {
                fee += billWaterElecVO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(officeName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setUnpayTotal(fee);
                billRateVOMap.put(officeName, billRateVO);
            } else {
                billRateVO.setUnpayTotal(fee);
            }
        }

        //统计当期预收
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        if (calendar.get(Calendar.MONTH) != 11) {
            calendar.set(Calendar.MONTH, 11);
        }
        List<BillWaterDO> preBillWater = billWaterDAO.getBillList(suiteIdList, endDate, calendar.getTime(), 1);
        List<BillElecDO> preBillElec = billElecDAO.getBillList(suiteIdList, endDate, calendar.getTime(), 1);
        List<BillWaterElecVO> preWaterElecVOList = new ArrayList<BillWaterElecVO>(preBillWater.size()+preBillElec.size());
        for(BillElecDO billElecDO:preBillElec){
            preWaterElecVOList.add(new BillWaterElecVO(billElecDO));
        }
        for(BillWaterDO billWaterDO:preBillWater){
            preWaterElecVOList.add(new BillWaterElecVO(billWaterDO));
        }

        Map<Long, List<BillWaterElecVO>> preBillMap = new HashMap<Long, List<BillWaterElecVO>>();
        for (BillWaterElecVO billWaterElecVO : preWaterElecVOList) {
            SuiteDO suiteDO = suiteDOMap.get(billWaterElecVO.getSuiteId());
            List<BillWaterElecVO> billWaterElecVOList = preBillMap.get(suiteDO.getOfficeVarId());
            if (billWaterElecVOList == null) {
                billWaterElecVOList = new ArrayList<BillWaterElecVO>();
                billWaterElecVOList.add(billWaterElecVO);
                preBillMap.put(suiteDO.getOfficeVarId(), billWaterElecVOList);
            } else {
                billWaterElecVOList.add(billWaterElecVO);
            }
        }
        Iterator<Map.Entry<Long, List<BillWaterElecVO>>> preIterator = preBillMap.entrySet().iterator();
        while (preIterator.hasNext()) {
            Map.Entry<Long, List<BillWaterElecVO>> next = preIterator.next();
            Long varId = next.getKey();
            List<BillWaterElecVO> billWaterElecVOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String officeName = "未分类";
            if (sysVarDO != null) {
                officeName = sysVarDO.getVarValue();
            }
            long fee = 0;
            for (BillWaterElecVO billWaterElecVO : billWaterElecVOList) {
                fee += billWaterElecVO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(officeName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setPreTotal(fee);
                billRateVOMap.put(officeName, billRateVO);
            } else {
                billRateVO.setPreTotal(fee);
            }
        }

        //统计次年预收
        int year = calendar.get(Calendar.YEAR);
        List<BillWaterDO> preNextYearBillWater = billWaterDAO.getBillByYear(suiteIdList, year + 1, 1);
        List<BillElecDO> preNextYearBillElec = billElecDAO.getBillByYear(suiteIdList, year + 1, 1);
        List<BillWaterElecVO> preNextWaterElecVOList = new ArrayList<BillWaterElecVO>(preNextYearBillWater.size()+preNextYearBillElec.size());
        for(BillElecDO billElecDO:preNextYearBillElec){
            preNextWaterElecVOList.add(new BillWaterElecVO(billElecDO));
        }
        for(BillWaterDO billWaterDO:preNextYearBillWater){
            preNextWaterElecVOList.add(new BillWaterElecVO(billWaterDO));
        }
        Map<Long, List<BillWaterElecVO>> preNextYearBillMap = new HashMap<Long, List<BillWaterElecVO>>();
        for (BillWaterElecVO billWaterElecVO : preNextWaterElecVOList) {
            SuiteDO suiteDO = suiteDOMap.get(billWaterElecVO.getSuiteId());
            List<BillWaterElecVO> billWaterElecVOList = preNextYearBillMap.get(suiteDO.getOfficeVarId());
            if (billWaterElecVOList == null) {
                billWaterElecVOList = new ArrayList<BillWaterElecVO>();
                billWaterElecVOList.add(billWaterElecVO);
                preNextYearBillMap.put(suiteDO.getOfficeVarId(), billWaterElecVOList);
            } else {
                billWaterElecVOList.add(billWaterElecVO);
            }
        }
        Iterator<Map.Entry<Long, List<BillWaterElecVO>>> preNextYearIterator = preNextYearBillMap.entrySet().iterator();
        while (preNextYearIterator.hasNext()) {
            Map.Entry<Long, List<BillWaterElecVO>> next = preNextYearIterator.next();
            Long varId = next.getKey();
            List<BillWaterElecVO> estateDOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String officeName = "未分类";
            if (sysVarDO != null) {
                officeName = sysVarDO.getVarValue();
            }
            long fee = 0;
            for (BillWaterElecVO billWaterElecVO : estateDOList) {
                fee += billWaterElecVO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(officeName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setPreTotalNextYear(fee);
                billRateVOMap.put(officeName, billRateVO);
            } else {
                billRateVO.setPreTotalNextYear(fee);
            }
        }

        //移除不需要统计的
        if (statFeeForm.getSubType() != null) {
            SysVarDO sysVarDO = sysVarDOMap.get(statFeeForm.getSubType());
            if (sysVarDO != null) {
                Iterator<String> iterator1 = billRateVOMap.keySet().iterator();
                if (iterator1.hasNext()) {
                    String key = iterator1.next();
                    if (!key.equals(sysVarDO.getVarValue())) {
                        billRateVOMap.remove(key);
                    }
                }
            }
        }
    }




    private void statWaterElecByVillage(BizResult bizResult, List<BillWaterElecVO> bill, Map<Long, SuiteDO> suiteDOMap, StatFeeForm statFeeForm, Date startDate, Date endDate, List<Long> suiteIdList) {
        //按小区分组
        Map<String, BillRateVO> billRateVOMap = new HashMap<String, BillRateVO>();
        VillageDO villageById = villageDAO.getVillageById(statFeeForm.getVillageId());
        BillRateVO billRateVO = statWaterElecRate(bill);
        billRateVOMap.put(villageById.getVillageName(), billRateVO);


        bizResult.data.put("billRateVOMap", billRateVOMap);
        //统计历年欠费
        List<BillEstateDO> unpayBill = billEstateDAO.getBill(suiteIdList, null, startDate, 0);
        long fee = 0;
        for (BillEstateDO billEstateDO : unpayBill) {
            fee += billEstateDO.getPayTotal();
        }
        billRateVO.setUnpayTotal(fee);

        //统计当期预收
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        if (calendar.get(Calendar.MONTH) != 11) {
            calendar.set(Calendar.MONTH, 11);
        }
        List<BillWaterDO> preBillWater = billWaterDAO.getBillList(suiteIdList, endDate, calendar.getTime(), 1);
        List<BillElecDO> preBillElec = billElecDAO.getBillList(suiteIdList, endDate, calendar.getTime(), 1);

        fee = 0;
        for (BillWaterDO billWaterDO : preBillWater) {
            fee += billWaterDO.getPayTotal();
        }
        for (BillElecDO billElecDO : preBillElec) {
            fee += billElecDO.getPayTotal();
        }

        billRateVO.setPreTotal(fee);


        //统计次年预收
        int year = calendar.get(Calendar.YEAR);
        List<BillWaterDO> preNextYearBillWater = billWaterDAO.getBillByYear(suiteIdList, year + 1, 1);
        List<BillElecDO> preNextYearBillElec = billElecDAO.getBillByYear(suiteIdList, year + 1, 1);
        fee = 0;
        for (BillWaterDO billWaterDO : preNextYearBillWater) {
            fee += billWaterDO.getPayTotal();
        }
        for (BillElecDO billElecDO : preNextYearBillElec) {
            fee += billElecDO.getPayTotal();
        }

        billRateVO.setPreTotalNextYear(fee);



    }


    private void statWaterElecByManage(BizResult bizResult, List<BillWaterElecVO> bill, Map<Long, SuiteDO> suiteDOMap
            , StatFeeForm statFeeForm, Date startDate, Date endDate, List<Long> suiteIdList) {
        //按办公室分组
        Map<Long, List<BillWaterElecVO>> billMap = new HashMap<Long, List<BillWaterElecVO>>();
        for (BillWaterElecVO billWaterElecVO : bill) {
            SuiteDO suiteDO = suiteDOMap.get(billWaterElecVO.getSuiteId());
            List<BillWaterElecVO> billWaterElecVOList = billMap.get(suiteDO.getEmployeeId());
            if (billWaterElecVOList == null) {
                billWaterElecVOList = new ArrayList<BillWaterElecVO>();
                billWaterElecVOList.add(billWaterElecVO);
                billMap.put(suiteDO.getEmployeeId(), billWaterElecVOList);
            } else {
                billWaterElecVOList.add(billWaterElecVO);
            }
        }
        OfficeEmployeeQuery officeEmployeeQuery = new OfficeEmployeeQuery();
        officeEmployeeQuery.setVillageId(statFeeForm.getVillageId());
        officeEmployeeQuery.setPageSize(5000);
        List<OfficeEmployeeDO> officeEmployeeDOList = officeEmployeeDAO.selectForPage(officeEmployeeQuery);
        Map<Long, OfficeEmployeeDO> officeEmployeeDOMap = new HashMap<Long, OfficeEmployeeDO>();
        for (OfficeEmployeeDO officeEmployeeDO : officeEmployeeDOList) {
            officeEmployeeDOMap.put(officeEmployeeDO.getEmployeeId(), officeEmployeeDO);
        }
        Map<String, BillRateVO> billRateVOMap = new HashMap<String, BillRateVO>();
        Iterator<Map.Entry<Long, List<BillWaterElecVO>>> iterator = billMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Long, List<BillWaterElecVO>> next = iterator.next();
            Long varId = next.getKey();
            List<BillWaterElecVO> billWaterElecVOList = next.getValue();
            OfficeEmployeeDO officeEmployeeDO = officeEmployeeDOMap.get(varId);
            String groupName = "未分类";
            if (officeEmployeeDO != null) {
                groupName = officeEmployeeDO.getUserName();
            }
            BillRateVO billRateVO = statWaterElecRate(billWaterElecVOList);
            billRateVOMap.put(groupName, billRateVO);
        }

        bizResult.data.put("billRateVOMap", billRateVOMap);
        //统计历年欠费
        List<BillWaterDO> unpayBillWater = billWaterDAO.getBillList(suiteIdList, null, startDate, 0);
        List<BillElecDO> unpayBillElec = billElecDAO.getBillList(suiteIdList, null, startDate, 0);
        List<BillWaterElecVO> unpayBill = new ArrayList<BillWaterElecVO>(unpayBillWater.size()+unpayBillElec.size());
        for(BillElecDO billElecDO:unpayBillElec){
            unpayBill.add(new BillWaterElecVO(billElecDO));
        }
        for(BillWaterDO billWaterDO:unpayBillWater){
            unpayBill.add(new BillWaterElecVO(billWaterDO));
        }
        Map<Long, List<BillWaterElecVO>> unpayBillMap = new HashMap<Long, List<BillWaterElecVO>>();
        for (BillWaterElecVO billWaterElecVO : unpayBill) {
            SuiteDO suiteDO = suiteDOMap.get(billWaterElecVO.getSuiteId());
            List<BillWaterElecVO> billWaterElecVOList = unpayBillMap.get(suiteDO.getEmployeeId());
            if (billWaterElecVOList == null) {
                billWaterElecVOList = new ArrayList<BillWaterElecVO>();
                billWaterElecVOList.add(billWaterElecVO);
                unpayBillMap.put(suiteDO.getEmployeeId(), billWaterElecVOList);
            } else {
                billWaterElecVOList.add(billWaterElecVO);
            }
        }
        Iterator<Map.Entry<Long, List<BillWaterElecVO>>> unpayIterator = unpayBillMap.entrySet().iterator();
        while (unpayIterator.hasNext()) {
            Map.Entry<Long, List<BillWaterElecVO>> next = unpayIterator.next();
            Long varId = next.getKey();
            List<BillWaterElecVO> estateDOList = next.getValue();
            OfficeEmployeeDO officeEmployeeDO = officeEmployeeDOMap.get(varId);
            String groupName = "未分类";
            if (officeEmployeeDO != null) {
                groupName = officeEmployeeDO.getUserName();
            }
            long fee = 0;
            for (BillWaterElecVO billWaterElecVO : estateDOList) {
                fee += billWaterElecVO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setUnpayTotal(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setUnpayTotal(fee);
            }
        }

        //统计当期预收
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        if (calendar.get(Calendar.MONTH) != 11) {
            calendar.set(Calendar.MONTH, 11);
        }
        List<BillWaterDO> preBillWater = billWaterDAO.getBillList(suiteIdList, endDate, calendar.getTime(), 1);
        List<BillElecDO> preBillElec = billElecDAO.getBillList(suiteIdList, endDate, calendar.getTime(), 1);
        List<BillWaterElecVO> preBill = new ArrayList<BillWaterElecVO>(preBillWater.size()+preBillElec.size());
        for(BillElecDO billElecDO:preBillElec){
            preBill.add(new BillWaterElecVO(billElecDO));
        }
        for(BillWaterDO billWaterDO:preBillWater){
            preBill.add(new BillWaterElecVO(billWaterDO));
        }
        Map<Long, List<BillWaterElecVO>> preBillMap = new HashMap<Long, List<BillWaterElecVO>>();
        for (BillWaterElecVO billWaterElecVO : preBill) {
            SuiteDO suiteDO = suiteDOMap.get(billWaterElecVO.getSuiteId());
            List<BillWaterElecVO> billWaterElecVOList = preBillMap.get(suiteDO.getEmployeeId());
            if (billWaterElecVOList == null) {
                billWaterElecVOList = new ArrayList<BillWaterElecVO>();
                billWaterElecVOList.add(billWaterElecVO);
                preBillMap.put(suiteDO.getOfficeVarId(), billWaterElecVOList);
            } else {
                billWaterElecVOList.add(billWaterElecVO);
            }
        }
        Iterator<Map.Entry<Long, List<BillWaterElecVO>>> preIterator = preBillMap.entrySet().iterator();
        while (preIterator.hasNext()) {
            Map.Entry<Long, List<BillWaterElecVO>> next = preIterator.next();
            Long varId = next.getKey();
            List<BillWaterElecVO> billWaterElecVOList = next.getValue();
            OfficeEmployeeDO officeEmployeeDO = officeEmployeeDOMap.get(varId);
            String groupName = "未分类";
            if (officeEmployeeDO != null) {
                groupName = officeEmployeeDO.getUserName();
            }
            long fee = 0;
            for (BillWaterElecVO billWaterElecVO : billWaterElecVOList) {
                fee += billWaterElecVO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setPreTotal(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setPreTotal(fee);
            }
        }

        //统计次年预收
        int year = calendar.get(Calendar.YEAR);
        List<BillWaterDO> preNextYearBillWater = billWaterDAO.getBillByYear(suiteIdList, year + 1, 1);
        List<BillElecDO> preNextYearBillElec = billElecDAO.getBillByYear(suiteIdList, year + 1, 1);
        List<BillWaterElecVO> preNextYearBill = new ArrayList<BillWaterElecVO>(preNextYearBillWater.size()+preNextYearBillElec.size());
        for(BillElecDO billElecDO:preNextYearBillElec){
            preNextYearBill.add(new BillWaterElecVO(billElecDO));
        }
        for(BillWaterDO billWaterDO:preNextYearBillWater){
            preNextYearBill.add(new BillWaterElecVO(billWaterDO));
        }
        Map<Long, List<BillWaterElecVO>> preNextYearBillMap = new HashMap<Long, List<BillWaterElecVO>>();
        for (BillWaterElecVO billWaterElecVO : preNextYearBill) {
            SuiteDO suiteDO = suiteDOMap.get(billWaterElecVO.getSuiteId());
            List<BillWaterElecVO> billWaterElecVOList = preNextYearBillMap.get(suiteDO.getEmployeeId());
            if (billWaterElecVOList == null) {
                billWaterElecVOList = new ArrayList<BillWaterElecVO>();
                billWaterElecVOList.add(billWaterElecVO);
                preNextYearBillMap.put(suiteDO.getEmployeeId(), billWaterElecVOList);
            } else {
                billWaterElecVOList.add(billWaterElecVO);
            }
        }
        Iterator<Map.Entry<Long, List<BillWaterElecVO>>> preNextYearIterator = preNextYearBillMap.entrySet().iterator();
        while (preNextYearIterator.hasNext()) {
            Map.Entry<Long, List<BillWaterElecVO>> next = preNextYearIterator.next();
            Long varId = next.getKey();
            List<BillWaterElecVO> billWaterElecVOList = next.getValue();
            OfficeEmployeeDO officeEmployeeDO = officeEmployeeDOMap.get(varId);
            String groupName = "未分类";
            if (officeEmployeeDO != null) {
                groupName = officeEmployeeDO.getUserName();
            }
            long fee = 0;
            for (BillWaterElecVO billWaterElecVO : billWaterElecVOList) {
                fee += billWaterElecVO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setPreTotalNextYear(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setPreTotalNextYear(fee);
            }
        }


        //移除不需要统计的
        if (statFeeForm.getSubType() != null) {
            OfficeEmployeeDO officeEmployeeDO = officeEmployeeDOMap.get(statFeeForm.getSubType());
            if (officeEmployeeDO != null) {
                Iterator<String> iterator1 = billRateVOMap.keySet().iterator();
                if (iterator1.hasNext()) {
                    String key = iterator1.next();
                    if (!key.equals(officeEmployeeDO.getUserName())) {
                        billRateVOMap.remove(key);
                    }
                }
            }
        }
    }

    private void statWaterElecByBuilding(BizResult bizResult, List<BillWaterElecVO> bill, Map<Long, SuiteDO> suiteDOMap
            , StatFeeForm statFeeForm, Date startDate, Date endDate, List<Long> suiteIdList) {
        //按楼栋分组
        BuildingQuery buildingQuery = new BuildingQuery();
        buildingQuery.setVillageId(statFeeForm.getVillageId());
        List<BuildingDO> buildingDOs = buildingDAO.selectForPage(buildingQuery);
        Map<Long, BuildingDO> buildingDOMap = new HashMap<Long, BuildingDO>();
        for (BuildingDO buildingDO : buildingDOs) {
            buildingDOMap.put(buildingDO.getBuildingId(), buildingDO);
        }

        List<Long> buildingIdList = TransformHelper.transform(buildingDOs, new Transform<BuildingDO, Long>() {
            @Override
            public Long transform(BuildingDO object) {
                return object.getBuildingId();
            }
        });
        if (buildingIdList.size() == 0) {
            bizResult.success = true;
            return;
        }

        Map<Long, Long> buildingSuiteMap = new HashMap<Long, Long>();
        for (Long buildingId : buildingIdList) {
            UnitQuery unitQuery = new UnitQuery();
            unitQuery.setPageSize(10000);
            unitQuery.setBuildingId(buildingId);
            List<UnitDO> unitDOs = unitDAO.selectForPage(unitQuery);
            List<Long> unitIdList = TransformHelper.transform(unitDOs, new Transform<UnitDO, Long>() {
                @Override
                public Long transform(UnitDO object) {
                    return object.getUnitId();
                }
            });
            if (unitIdList.size() == 0) {
                continue;
            }

            SuiteQuery suiteQuery = new SuiteQuery();
            suiteQuery.setPageSize(10000);
            suiteQuery.setUnitIdList(unitIdList);
            List<SuiteDO> suiteDOs = suiteDAO.selectForPage(suiteQuery);
            for (SuiteDO suiteDO : suiteDOs) {
                buildingSuiteMap.put(suiteDO.getSuiteId(), buildingId);
            }
        }


        Map<Long, List<BillWaterElecVO>> billMap = new HashMap<Long, List<BillWaterElecVO>>();
        for (BillWaterElecVO waterElecVO : bill) {
            SuiteDO suiteDO = suiteDOMap.get(waterElecVO.getSuiteId());
            Long buildingId = buildingSuiteMap.get(suiteDO.getSuiteId());
            List<BillWaterElecVO> billWaterElecVOList = billMap.get(buildingId);
            if (billWaterElecVOList == null) {
                billWaterElecVOList = new ArrayList<BillWaterElecVO>();
                billWaterElecVOList.add(waterElecVO);
                billMap.put(buildingId, billWaterElecVOList);
            } else {
                billWaterElecVOList.add(waterElecVO);
            }
        }

        Map<String, BillRateVO> billRateVOMap = new HashMap<String, BillRateVO>();
        Iterator<Map.Entry<Long, List<BillWaterElecVO>>> iterator = billMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Long, List<BillWaterElecVO>> next = iterator.next();
            Long varId = next.getKey();
            List<BillWaterElecVO> estateDOList = next.getValue();
            BuildingDO buildingDO = buildingDOMap.get(varId);
            String groupName = "未分类";
            if (buildingDO != null) {
                groupName = buildingDO.getBuildingName();
            }
            BillRateVO billRateVO = statWaterElecRate(estateDOList);
            billRateVOMap.put(groupName, billRateVO);
        }

        bizResult.data.put("billRateVOMap", billRateVOMap);
        //统计历年欠费
        List<BillWaterDO> unpayBillWater = billWaterDAO.getBillList(suiteIdList, null, startDate, 0);
        List<BillElecDO> unpayBillElec = billElecDAO.getBillList(suiteIdList, null, startDate, 0);
        List<BillWaterElecVO> unpayBill = new ArrayList<BillWaterElecVO>(unpayBillWater.size()+unpayBillElec.size());
        for(BillElecDO billElecDO:unpayBillElec){
            unpayBill.add(new BillWaterElecVO(billElecDO));
        }
        for(BillWaterDO billWaterDO:unpayBillWater){
            unpayBill.add(new BillWaterElecVO(billWaterDO));
        }
        Map<Long, List<BillWaterElecVO>> unpayBillMap = new HashMap<Long, List<BillWaterElecVO>>();
        for (BillWaterElecVO billWaterElecVO : unpayBill) {
            SuiteDO suiteDO = suiteDOMap.get(billWaterElecVO.getSuiteId());
            List<BillWaterElecVO> billWaterElecVOList = unpayBillMap.get(suiteDO.getEmployeeId());
            if (billWaterElecVOList == null) {
                billWaterElecVOList = new ArrayList<BillWaterElecVO>();
                billWaterElecVOList.add(billWaterElecVO);
                unpayBillMap.put(suiteDO.getEmployeeId(), billWaterElecVOList);
            } else {
                billWaterElecVOList.add(billWaterElecVO);
            }
        }
        Iterator<Map.Entry<Long, List<BillWaterElecVO>>> unpayIterator = unpayBillMap.entrySet().iterator();
        while (unpayIterator.hasNext()) {
            Map.Entry<Long, List<BillWaterElecVO>> next = unpayIterator.next();
            Long varId = next.getKey();
            List<BillWaterElecVO> estateDOList = next.getValue();
            BuildingDO buildingDO = buildingDOMap.get(varId);
            String groupName = "未分类";
            if (buildingDO != null) {
                groupName = buildingDO.getBuildingName();
            }
            long fee = 0;
            for (BillWaterElecVO billWaterElecVO : estateDOList) {
                fee += billWaterElecVO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setUnpayTotal(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setUnpayTotal(fee);
            }
        }

        //统计当期预收
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        if (calendar.get(Calendar.MONTH) != 11) {
            calendar.set(Calendar.MONTH, 11);
        }
        List<BillWaterDO> preBillWater = billWaterDAO.getBillList(suiteIdList, endDate, calendar.getTime(), 1);
        List<BillElecDO> preBillElec = billElecDAO.getBillList(suiteIdList, endDate, calendar.getTime(), 1);
        List<BillWaterElecVO> preBill = new ArrayList<BillWaterElecVO>(preBillWater.size()+preBillElec.size());
        for(BillElecDO billElecDO:preBillElec){
            preBill.add(new BillWaterElecVO(billElecDO));
        }
        for(BillWaterDO billWaterDO:preBillWater){
            preBill.add(new BillWaterElecVO(billWaterDO));
        }
        Map<Long, List<BillWaterElecVO>> preBillMap = new HashMap<Long, List<BillWaterElecVO>>();
        for (BillWaterElecVO billWaterElecVO : preBill) {
            SuiteDO suiteDO = suiteDOMap.get(billWaterElecVO.getSuiteId());
            List<BillWaterElecVO> billWaterElecVOList = preBillMap.get(suiteDO.getEmployeeId());
            if (billWaterElecVOList == null) {
                billWaterElecVOList = new ArrayList<BillWaterElecVO>();
                billWaterElecVOList.add(billWaterElecVO);
                preBillMap.put(suiteDO.getOfficeVarId(), billWaterElecVOList);
            } else {
                billWaterElecVOList.add(billWaterElecVO);
            }
        }
        Iterator<Map.Entry<Long, List<BillWaterElecVO>>> preIterator = preBillMap.entrySet().iterator();
        while (preIterator.hasNext()) {
            Map.Entry<Long, List<BillWaterElecVO>> next = preIterator.next();
            Long varId = next.getKey();
            List<BillWaterElecVO> estateDOList = next.getValue();
            BuildingDO buildingDO = buildingDOMap.get(varId);
            String groupName = "未分类";
            if (buildingDO != null) {
                groupName = buildingDO.getBuildingName();
            }
            long fee = 0;
            for (BillWaterElecVO billWaterElecVO : estateDOList) {
                fee += billWaterElecVO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setPreTotal(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setPreTotal(fee);
            }
        }

        //统计次年预收
        int year = calendar.get(Calendar.YEAR);
        List<BillWaterDO> preNextYearBillWater = billWaterDAO.getBillByYear(suiteIdList, year + 1, 1);
        List<BillElecDO> preNextYearBillElec = billElecDAO.getBillByYear(suiteIdList, year + 1, 1);
        List<BillWaterElecVO> preNextYearBill = new ArrayList<BillWaterElecVO>(preNextYearBillWater.size()+preNextYearBillElec.size());
        for(BillElecDO billElecDO:preNextYearBillElec){
            preNextYearBill.add(new BillWaterElecVO(billElecDO));
        }
        for(BillWaterDO billWaterDO:preNextYearBillWater){
            preNextYearBill.add(new BillWaterElecVO(billWaterDO));
        }
        Map<Long, List<BillWaterElecVO>> preNextYearBillMap = new HashMap<Long, List<BillWaterElecVO>>();
        for (BillWaterElecVO billWaterElecVO : preNextYearBill) {
            SuiteDO suiteDO = suiteDOMap.get(billWaterElecVO.getSuiteId());
            List<BillWaterElecVO> billWaterElecVOList = preNextYearBillMap.get(suiteDO.getEmployeeId());
            if (billWaterElecVOList == null) {
                billWaterElecVOList = new ArrayList<BillWaterElecVO>();
                billWaterElecVOList.add(billWaterElecVO);
                preNextYearBillMap.put(suiteDO.getEmployeeId(), billWaterElecVOList);
            } else {
                billWaterElecVOList.add(billWaterElecVO);
            }
        }
        Iterator<Map.Entry<Long, List<BillWaterElecVO>>> preNextYearIterator = preNextYearBillMap.entrySet().iterator();
        while (preNextYearIterator.hasNext()) {
            Map.Entry<Long, List<BillWaterElecVO>> next = preNextYearIterator.next();
            Long varId = next.getKey();
            List<BillWaterElecVO> estateDOList = next.getValue();
            BuildingDO buildingDO = buildingDOMap.get(varId);
            String groupName = "未分类";
            if (buildingDO != null) {
                groupName = buildingDO.getBuildingName();
            }
            long fee = 0;
            for (BillWaterElecVO billWaterElecVO : estateDOList) {
                fee += billWaterElecVO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setPreTotalNextYear(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setPreTotalNextYear(fee);
            }
        }


        //移除不需要统计的
        if (statFeeForm.getSubType() != null) {
            BuildingDO buildingDO = buildingDOMap.get(statFeeForm.getSubType());
            if (buildingDO != null) {
                Iterator<String> iterator1 = billRateVOMap.keySet().iterator();
                if (iterator1.hasNext()) {
                    String key = iterator1.next();
                    if (!key.equals(buildingDO.getBuildingName())) {
                        billRateVOMap.remove(key);
                    }
                }
            }
        }
    }


    private void statWaterElecByBuildingType(BizResult bizResult, List<BillWaterElecVO> bill, Map<Long, SuiteDO> suiteDOMap
            , StatFeeForm statFeeForm, Date startDate, Date endDate, List<Long> suiteIdList) {
        //按建筑类型分组
        BuildingQuery buildingQuery = new BuildingQuery();
        buildingQuery.setVillageId(statFeeForm.getVillageId());
        List<BuildingDO> buildingDOs = buildingDAO.selectForPage(buildingQuery);
        Map<Long, BuildingDO> buildingDOMap = new HashMap<Long, BuildingDO>();
        for (BuildingDO buildingDO : buildingDOs) {
            buildingDOMap.put(buildingDO.getBuildingId(), buildingDO);
        }

        List<Long> buildingIdList = TransformHelper.transform(buildingDOs, new Transform<BuildingDO, Long>() {
            @Override
            public Long transform(BuildingDO object) {
                return object.getBuildingId();
            }
        });
        if (buildingIdList.size() == 0) {
            bizResult.success = true;
            return;
        }

        Map<Long, Long> buildingSuiteMap = new HashMap<Long, Long>();
        for (Long buildingId : buildingIdList) {
            UnitQuery unitQuery = new UnitQuery();
            unitQuery.setPageSize(10000);
            unitQuery.setBuildingId(buildingId);
            List<UnitDO> unitDOs = unitDAO.selectForPage(unitQuery);
            List<Long> unitIdList = TransformHelper.transform(unitDOs, new Transform<UnitDO, Long>() {
                @Override
                public Long transform(UnitDO object) {
                    return object.getUnitId();
                }
            });
            if (unitIdList.size() == 0) {
                continue;
            }

            SuiteQuery suiteQuery = new SuiteQuery();
            suiteQuery.setPageSize(10000);
            suiteQuery.setUnitIdList(unitIdList);
            List<SuiteDO> suiteDOs = suiteDAO.selectForPage(suiteQuery);
            for (SuiteDO suiteDO : suiteDOs) {
                buildingSuiteMap.put(suiteDO.getSuiteId(), buildingId);
            }
        }

        SysVarQuery sysVarQuery = new SysVarQuery();
        sysVarQuery.setVillageId(statFeeForm.getVillageId());
        sysVarQuery.setPageSize(500);
        sysVarQuery.setVarType(SysVarTypeEnum.building.name());
        List<SysVarDO> sysVarDOs = sysVarDAO.selectForView(sysVarQuery);
        Map<Long, SysVarDO> sysVarDOMap = new HashMap<Long, SysVarDO>();
        for (SysVarDO sysVarDO : sysVarDOs) {
            sysVarDOMap.put(sysVarDO.getVarId(), sysVarDO);
        }

        Map<Long, List<BillWaterElecVO>> billMap = new HashMap<Long, List<BillWaterElecVO>>();
        for (BillWaterElecVO billWaterElecVO : bill) {
            SuiteDO suiteDO = suiteDOMap.get(billWaterElecVO.getSuiteId());
            //Long buildingId = buildingSuiteMap.get(suiteDO.getSuiteId());
            //BuildingDO buildingDO = buildingDOMap.get(buildingId);
            List<BillWaterElecVO> billWaterElecVOList = billMap.get(suiteDO.getBuildingTypeId());
            if (billWaterElecVOList == null) {
                billWaterElecVOList = new ArrayList<BillWaterElecVO>();
                billWaterElecVOList.add(billWaterElecVO);
                billMap.put(suiteDO.getBuildingTypeId(), billWaterElecVOList);
            } else {
                billWaterElecVOList.add(billWaterElecVO);
            }
        }

        Map<String, BillRateVO> billRateVOMap = new HashMap<String, BillRateVO>();
        Iterator<Map.Entry<Long, List<BillWaterElecVO>>> iterator = billMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Long, List<BillWaterElecVO>> next = iterator.next();
            Long varId = next.getKey();
            List<BillWaterElecVO> billWaterElecVOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String groupName = "未分类";
            if (sysVarDO != null) {
                groupName = sysVarDO.getVarValue();
            }
            BillRateVO billRateVO = statWaterElecRate(billWaterElecVOList);
            //统计总房数
            Set<Long> totalSuiteIdSet = TransformHelper.transform2Set(billWaterElecVOList, new Transform<BillWaterElecVO, Long>() {
                @Override
                public Long transform(BillWaterElecVO object) {
                    return object.getSuiteId();
                }
            });
            billRateVO.setSuiteTotal(totalSuiteIdSet.size());
            //统计交房数
            int deliveryTotal = 0;
            for (Long suiteId : totalSuiteIdSet) {
                SuiteDO suiteDO = suiteDOMap.get(suiteId);
                if (suiteDO.getGmtDelivery() != null) {
                    deliveryTotal++;
                }
            }
            billRateVO.setSuiteDeliverTotal(deliveryTotal);
            billRateVOMap.put(groupName, billRateVO);
        }

        bizResult.data.put("billRateVOMap", billRateVOMap);
        //统计历年欠费
        List<BillWaterDO> unpayBillWater = billWaterDAO.getBillList(suiteIdList, null, startDate, 0);
        List<BillElecDO> unpayBillElec = billElecDAO.getBillList(suiteIdList, null, startDate, 0);
        List<BillWaterElecVO> unpayBill = new ArrayList<BillWaterElecVO>(unpayBillWater.size()+unpayBillElec.size());
        for(BillElecDO billElecDO:unpayBillElec){
            unpayBill.add(new BillWaterElecVO(billElecDO));
        }
        for(BillWaterDO billWaterDO:unpayBillWater){
            unpayBill.add(new BillWaterElecVO(billWaterDO));
        }
        Map<Long, List<BillWaterElecVO>> unpayBillMap = new HashMap<Long, List<BillWaterElecVO>>();
        for (BillWaterElecVO billWaterElecVO : unpayBill) {
            SuiteDO suiteDO = suiteDOMap.get(billWaterElecVO.getSuiteId());
            //Long buildingId = buildingSuiteMap.get(suiteDO.getSuiteId());
            //BuildingDO buildingDO = buildingDOMap.get(buildingId);
            List<BillWaterElecVO> billWaterElecVOList = unpayBillMap.get(suiteDO.getBuildingTypeId());
            if (billWaterElecVOList == null) {
                billWaterElecVOList = new ArrayList<BillWaterElecVO>();
                billWaterElecVOList.add(billWaterElecVO);
                unpayBillMap.put(suiteDO.getBuildingTypeId(), billWaterElecVOList);
            } else {
                billWaterElecVOList.add(billWaterElecVO);
            }
        }
        Iterator<Map.Entry<Long, List<BillWaterElecVO>>> unpayIterator = unpayBillMap.entrySet().iterator();
        while (unpayIterator.hasNext()) {
            Map.Entry<Long, List<BillWaterElecVO>> next = unpayIterator.next();
            Long varId = next.getKey();
            List<BillWaterElecVO> billWaterElecVOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String groupName = "未分类";
            if (sysVarDO != null) {
                groupName = sysVarDO.getVarValue();
            }
            long fee = 0;
            for (BillWaterElecVO billWaterElecVO : billWaterElecVOList) {
                fee += billWaterElecVO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setUnpayTotal(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setUnpayTotal(fee);
            }
        }

        //统计当期预收
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        if (calendar.get(Calendar.MONTH) != 11) {
            calendar.set(Calendar.MONTH, 11);
        }
        List<BillWaterDO> preBillWater = billWaterDAO.getBillList(suiteIdList, endDate, calendar.getTime(), 1);
        List<BillElecDO> preBillElec = billElecDAO.getBillList(suiteIdList, endDate, calendar.getTime(), 1);
        List<BillWaterElecVO> preBill = new ArrayList<BillWaterElecVO>(preBillWater.size()+preBillElec.size());
        for(BillElecDO billElecDO:preBillElec){
            preBill.add(new BillWaterElecVO(billElecDO));
        }
        for(BillWaterDO billWaterDO:preBillWater){
            preBill.add(new BillWaterElecVO(billWaterDO));
        }
        Map<Long, List<BillWaterElecVO>> preBillMap = new HashMap<Long, List<BillWaterElecVO>>();
        for (BillWaterElecVO billWaterElecVO : preBill) {
            SuiteDO suiteDO = suiteDOMap.get(billWaterElecVO.getSuiteId());
            //Long buildingId = buildingSuiteMap.get(suiteDO.getSuiteId());
            //BuildingDO buildingDO = buildingDOMap.get(buildingId);
            List<BillWaterElecVO> billWaterElecVOList = preBillMap.get(suiteDO.getBuildingTypeId());
            if (billWaterElecVOList == null) {
                billWaterElecVOList = new ArrayList<BillWaterElecVO>();
                billWaterElecVOList.add(billWaterElecVO);
                preBillMap.put(suiteDO.getBuildingTypeId(), billWaterElecVOList);
            } else {
                billWaterElecVOList.add(billWaterElecVO);
            }
        }
        Iterator<Map.Entry<Long, List<BillWaterElecVO>>> preIterator = preBillMap.entrySet().iterator();
        while (preIterator.hasNext()) {
            Map.Entry<Long, List<BillWaterElecVO>> next = preIterator.next();
            Long varId = next.getKey();
            List<BillWaterElecVO> billWaterElecVOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String groupName = "未分类";
            if (sysVarDO != null) {
                groupName = sysVarDO.getVarValue();
            }
            long fee = 0;
            for (BillWaterElecVO billWaterElecVO : billWaterElecVOList) {
                fee += billWaterElecVO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setPreTotal(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setPreTotal(fee);
            }
        }

        //统计次年预收
        int year = calendar.get(Calendar.YEAR);
        List<BillWaterDO> preNextYearBillWater = billWaterDAO.getBillByYear(suiteIdList, year + 1, 1);
        List<BillElecDO> preNextYearBillElec = billElecDAO.getBillByYear(suiteIdList, year + 1, 1);
        List<BillWaterElecVO> preNextYearBill = new ArrayList<BillWaterElecVO>(preNextYearBillWater.size()+preNextYearBillElec.size());
        for(BillElecDO billElecDO:preNextYearBillElec){
            preNextYearBill.add(new BillWaterElecVO(billElecDO));
        }
        for(BillWaterDO billWaterDO:preNextYearBillWater){
            preNextYearBill.add(new BillWaterElecVO(billWaterDO));
        }
        Map<Long, List<BillWaterElecVO>> preNextYearBillMap = new HashMap<Long, List<BillWaterElecVO>>();
        for (BillWaterElecVO billWaterElecVO : preNextYearBill) {
            SuiteDO suiteDO = suiteDOMap.get(billWaterElecVO.getSuiteId());
            //Long buildingId = buildingSuiteMap.get(suiteDO.getSuiteId());
            //BuildingDO buildingDO = buildingDOMap.get(buildingId);
            List<BillWaterElecVO> billEstateDOList = preNextYearBillMap.get(suiteDO.getBuildingTypeId());
            if (billEstateDOList == null) {
                billEstateDOList = new ArrayList<BillWaterElecVO>();
                billEstateDOList.add(billWaterElecVO);
                preNextYearBillMap.put(suiteDO.getBuildingTypeId(), billEstateDOList);
            } else {
                billEstateDOList.add(billWaterElecVO);
            }
        }
        Iterator<Map.Entry<Long, List<BillWaterElecVO>>> preNextYearIterator = preNextYearBillMap.entrySet().iterator();
        while (preNextYearIterator.hasNext()) {
            Map.Entry<Long, List<BillWaterElecVO>> next = preNextYearIterator.next();
            Long varId = next.getKey();
            List<BillWaterElecVO> estateDOList = next.getValue();
            SysVarDO sysVarDO = sysVarDOMap.get(varId);
            String groupName = "未分类";
            if (sysVarDO != null) {
                groupName = sysVarDO.getVarValue();
            }
            long fee = 0;
            for (BillWaterElecVO billWaterElecVO : estateDOList) {
                fee += billWaterElecVO.getPayTotal();
            }
            BillRateVO billRateVO = billRateVOMap.get(groupName);
            if (billRateVO == null) {
                billRateVO = new BillRateVO();
                billRateVO.setPreTotalNextYear(fee);
                billRateVOMap.put(groupName, billRateVO);
            } else {
                billRateVO.setPreTotalNextYear(fee);
            }
        }


        //移除不需要统计的
        if (statFeeForm.getSubType() != null) {
            SysVarDO sysVarDO = sysVarDOMap.get(statFeeForm.getSubType());
            if (sysVarDO != null) {
                Iterator<String> iterator1 = billRateVOMap.keySet().iterator();
                if (iterator1.hasNext()) {
                    String key = iterator1.next();
                    if (!key.equals(sysVarDO.getVarValue())) {
                        billRateVOMap.remove(key);
                    }
                }
            }
        }
    }


    private BillStatVO statBillWithRefund(Date statDate, List<Long> suiteIdList, List<Long> parkingIdList,
                                          List<Long> depositVarIdList,
                                          List<Long> waterMeterSuiteIdList, List<Long> waterIcSuiteIdList,
                                          List<Long> elecMeterSuiteIdList, List<Long> elecIcSuiteIdList,
                                          Map<String, List<Long>> extVarMap,
                                          List<SysVarDO> extraSysVarDOs) {
        BillStatVO billStatVO = new BillStatVO();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String statDay = simpleDateFormat.format(statDate);
        long dichanTotal = 0;
        long selfTotal = 0;
        if (suiteIdList == null || suiteIdList.size() == 0) {
            billStatVO.setDepositPayTotal(0L);
            billStatVO.setElecPayTotal(0L);
            billStatVO.setEstatePayTotal(0L);
            billStatVO.setExtPayTotal(0L);
            billStatVO.setWaterPayTotal(0L);
            billStatVO.setDichanDiscount(0L);
            billStatVO.setSelfDiscount(0L);
        } else {
            Long estatePayTotal = billEstateDAO.statBill(suiteIdList, statDay, 1);
            Long dichanDiscountEstate = billEstateDAO.statDichanDiscount(suiteIdList, statDay);

            Long selfDiscountEstate = billEstateDAO.statSelfDiscount(suiteIdList, statDay);
            if (dichanDiscountEstate != null) {
                dichanTotal += dichanDiscountEstate;
            }
            if (selfDiscountEstate != null) {
                selfTotal += selfDiscountEstate;
            }
            if (waterMeterSuiteIdList.size() > 0) {
                Long waterMeterPayTotal = billWaterDAO.statBill(waterMeterSuiteIdList, statDay, 1);
                if (waterMeterPayTotal == null) {
                    billStatVO.setWaterMeterPayTotal(0L);
                } else {
                    billStatVO.setWaterMeterPayTotal(waterMeterPayTotal);
                }
            } else {
                billStatVO.setWaterMeterPayTotal(0L);
            }
            if (waterIcSuiteIdList.size() > 0) {
                Long waterIcPayTotal = billWaterDAO.statBill(waterIcSuiteIdList, statDay, 1);
                if (waterIcPayTotal == null) {
                    billStatVO.setWaterICPayTotal(0L);
                } else {
                    billStatVO.setWaterICPayTotal(waterIcPayTotal);
                }
            } else {
                billStatVO.setWaterICPayTotal(0L);
            }
            billStatVO.setWaterPayTotal(billStatVO.getWaterICPayTotal() + billStatVO.getWaterMeterPayTotal());

            Long dichanDiscountWater = billWaterDAO.statDichanDiscount(suiteIdList, statDay);
            Long selfDiscountWater = billWaterDAO.statSelfDiscount(suiteIdList, statDay);
            if (dichanDiscountWater != null) {
                dichanTotal += dichanDiscountWater;
            }
            if (selfDiscountWater != null) {
                selfTotal += selfDiscountWater;
            }
            if (elecIcSuiteIdList.size() > 0) {
                Long elecIc = billElecDAO.statBill(elecIcSuiteIdList, statDay, 1);
                if (elecIc == null) {
                    billStatVO.setElecICPayTotal(0L);
                } else {
                    billStatVO.setElecICPayTotal(elecIc);
                }
            } else {
                billStatVO.setElecICPayTotal(0L);
            }

            if (elecMeterSuiteIdList.size() > 0) {
                Long elecMeter = billElecDAO.statBill(elecMeterSuiteIdList, statDay, 1);
                if (elecMeter == null) {
                    billStatVO.setElecMeterPayTotal(0L);
                } else {
                    billStatVO.setElecMeterPayTotal(elecMeter);
                }
            } else {
                billStatVO.setElecMeterPayTotal(0L);
            }
            billStatVO.setElecPayTotal(billStatVO.getElecICPayTotal() + billStatVO.getElecMeterPayTotal());

            Long dichanDiscountElec = billElecDAO.statDichanDiscount(suiteIdList, statDay);
            Long selfDiscountElec = billElecDAO.statSelfDiscount(suiteIdList, statDay);
            if (dichanDiscountElec != null) {
                dichanTotal += dichanDiscountElec;
            }
            if (selfDiscountElec != null) {
                selfTotal += selfDiscountElec;
            }
            Long depositPayTotal = billExtDAO.statBill(suiteIdList, statDay, 1, depositVarIdList);
            if (depositPayTotal == null) {
                billStatVO.setDepositPayTotal(0L);
            } else {
                billStatVO.setDepositPayTotal(depositPayTotal);
            }

            Iterator<Map.Entry<String, List<Long>>> iterator = extVarMap.entrySet().iterator();
            List<StatObj> statObjs = new ArrayList<StatObj>();
            List<StatObj> refundObjs = new ArrayList<StatObj>();
            while (iterator.hasNext()) {
                Map.Entry<String, List<Long>> next = iterator.next();
                StatObj statObj = new StatObj();
                StatObj refund = new StatObj();
                Long extPayTotal = billExtDAO.statBill(suiteIdList, statDay, 1, next.getValue());
                Long aLong = billExtDAO.statRefund(suiteIdList, statDay, next.getValue());
                statObj.setName(next.getKey());
                refund.setName("退" + next.getKey());
                if (extPayTotal == null) {
                    statObj.setFeeTotal(0L);
                } else {
                    statObj.setFeeTotal(extPayTotal);
                }
                statObjs.add(statObj);

                if (aLong == null) {
                    refund.setFeeTotal(0L);
                } else {
                    refund.setFeeTotal(aLong);
                }
                refundObjs.add(refund);
            }
            billStatVO.setRefundObjList(refundObjs);
            billStatVO.setStatObjList(statObjs);
            List<StatObj> extraList = new ArrayList<StatObj>();
            for (SysVarDO sysVarDO : extraSysVarDOs) {
                StatObj statObj = new StatObj();
                Long aLong = extraFeeDAO.statBill(suiteIdList, statDay, sysVarDO.getVarId());
                statObj.setName(sysVarDO.getVarValue());
                if (aLong == null) {
                    statObj.setFeeTotal(0L);
                } else {
                    statObj.setFeeTotal(aLong);
                }
                extraList.add(statObj);
            }
            billStatVO.setExtraObjList(extraList);
            billStatVO.setEstatePayTotal(estatePayTotal);


            if (billStatVO.getElecPayTotal() == null) {
                billStatVO.setDepositPayTotal(0L);
            }
            if (estatePayTotal == null) {
                billStatVO.setEstatePayTotal(0L);
            }


            Long dichanDiscountExt = billExtDAO.statDichanDiscount(suiteIdList, statDay);
            Long selfDiscountExt = billExtDAO.statSelfDiscount(suiteIdList, statDay);
            if (dichanDiscountExt != null) {
                dichanTotal += dichanDiscountExt;
            }
            if (selfDiscountExt != null) {
                selfTotal += selfDiscountExt;
            }
        }
        if (parkingIdList == null || parkingIdList.size() == 0) {
            billStatVO.setParkingPayTotal(0L);
        } else {
            Long parkingPayTotal = billParkingDAO.statBill(parkingIdList, statDay, 1);
            billStatVO.setParkingPayTotal(parkingPayTotal);
            if (parkingPayTotal == null) {
                billStatVO.setParkingPayTotal(0L);
            }
            Long dichanDiscountExt = billParkingDAO.statDichanDiscount(parkingIdList, statDay);
            Long selfDiscountExt = billParkingDAO.statSelfDiscount(parkingIdList, statDay);
            if (dichanDiscountExt != null) {
                dichanTotal += dichanDiscountExt;
            }
            if (selfDiscountExt != null) {
                selfTotal += selfDiscountExt;
            }
        }
        billStatVO.setSelfDiscount(selfTotal);
        billStatVO.setDichanDiscount(dichanTotal);

        //统计物业支出
        Long bankStat = accountEstateDAO.stat(suiteIdList, statDay, AccountEstateTypeEnum.bank.name());
        List<StatObj> accountEstate = new ArrayList<StatObj>();
        StatObj bankStatObj = new StatObj();
        bankStatObj.setName(AccountEstateTypeEnum.bank.getDesc());
        if (bankStat == null) {
            bankStatObj.setFeeTotal(0L);
        } else {
            bankStatObj.setFeeTotal(bankStat);
        }
        accountEstate.add(bankStatObj);

        Long tansferStat = accountEstateDAO.stat(suiteIdList, statDay, AccountEstateTypeEnum.transfer.name());
        StatObj tansferStatObj = new StatObj();
        bankStatObj.setName(AccountEstateTypeEnum.transfer.getDesc());
        if (tansferStat == null) {
            tansferStatObj.setFeeTotal(0L);
        } else {
            tansferStatObj.setFeeTotal(tansferStat);
        }
        accountEstate.add(tansferStatObj);

        Long cardStat = accountEstateDAO.stat(suiteIdList, statDay, AccountEstateTypeEnum.card.name());
        StatObj cardStatObj = new StatObj();
        cardStatObj.setName(AccountEstateTypeEnum.card.getDesc());
        if (cardStat == null) {
            cardStatObj.setFeeTotal(0L);
        } else {
            cardStatObj.setFeeTotal(cardStat);
        }
        accountEstate.add(cardStatObj);

        Long weixinStat = accountEstateDAO.stat(suiteIdList, statDay, AccountEstateTypeEnum.weixin.name());
        StatObj weixinStatObj = new StatObj();
        bankStatObj.setName(AccountEstateTypeEnum.weixin.getDesc());
        if (tansferStat == null) {
            weixinStatObj.setFeeTotal(0L);
        } else {
            weixinStatObj.setFeeTotal(weixinStat);
        }
        accountEstate.add(weixinStatObj);

        billStatVO.setAccountEstateObjList(accountEstate);
        return billStatVO;
    }

    private List<Long> getSuiteIdList(StatFeeForm statFeeForm) {


        BuildingQuery buildingQuery = new BuildingQuery();
        buildingQuery.setPageSize(10000);
        if (statFeeForm.getBuildingType() != null) {
            buildingQuery.setBuildingTypeId(statFeeForm.getBuildingType());
        }
        buildingQuery.setVillageId(statFeeForm.getVillageId());
        List<BuildingDO> buildingDOs = buildingDAO.selectForPage(buildingQuery);
        List<Long> buildingIdList = TransformHelper.transform(buildingDOs, new Transform<BuildingDO, Long>() {
            @Override
            public Long transform(BuildingDO object) {
                return object.getBuildingId();
            }
        });
        if (buildingIdList.size() == 0) {
            return null;
        }

        UnitQuery unitQuery = new UnitQuery();
        unitQuery.setPageSize(10000);
        unitQuery.setBuildingIdList(buildingIdList);
        List<UnitDO> unitDOs = unitDAO.selectForPage(unitQuery);
        List<Long> unitIdList = TransformHelper.transform(unitDOs, new Transform<UnitDO, Long>() {
            @Override
            public Long transform(UnitDO object) {
                return object.getUnitId();
            }
        });
        if (unitIdList.size() == 0) {
            return null;
        }

        SuiteQuery suiteQuery = new SuiteQuery();
        suiteQuery.setPageSize(10000);
        suiteQuery.setUnitIdList(unitIdList);
        List<SuiteDO> suiteDOs = suiteDAO.selectForPage(suiteQuery);
        List<Long> suiteIdList = TransformHelper.transform(suiteDOs, new Transform<SuiteDO, Long>() {
            @Override
            public Long transform(SuiteDO object) {
                return object.getSuiteId();
            }
        });
        return suiteIdList;
    }


    private BillStatVO statBillByDay(Date statDate, List<Long> suiteIdList, List<Long> parkingIdList,
                                     List<Long> depositVarIdList,
                                     List<Long> waterMeterSuiteIdList, List<Long> waterIcSuiteIdList,
                                     List<Long> elecMeterSuiteIdList, List<Long> elecIcSuiteIdList,
                                     Map<String, List<Long>> extVarMap,
                                     List<SysVarDO> extraSysVarDOs) {
        BillStatVO billStatVO = new BillStatVO();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String statDay = simpleDateFormat.format(statDate);
        long dichanTotal = 0;
        long selfTotal = 0;
        if (suiteIdList == null || suiteIdList.size() == 0) {
            billStatVO.setDepositPayTotal(0L);
            billStatVO.setElecPayTotal(0L);
            billStatVO.setEstatePayTotal(0L);
            billStatVO.setExtPayTotal(0L);
            billStatVO.setWaterPayTotal(0L);
            billStatVO.setDichanDiscount(0L);
            billStatVO.setSelfDiscount(0L);
        } else {


            Long estatePayTotal = billEstateDAO.statBill(suiteIdList, statDay, 1);
            Long dichanDiscountEstate = billEstateDAO.statDichanDiscount(suiteIdList, statDay);

            Long selfDiscountEstate = billEstateDAO.statSelfDiscount(suiteIdList, statDay);
            if (dichanDiscountEstate != null) {
                dichanTotal += dichanDiscountEstate;
            }
            if (selfDiscountEstate != null) {
                selfTotal += selfDiscountEstate;
            }
            if (waterMeterSuiteIdList.size() > 0) {
                Long waterMeterPayTotal = billWaterDAO.statBill(waterMeterSuiteIdList, statDay, 1);
                if (waterMeterPayTotal == null) {
                    billStatVO.setWaterMeterPayTotal(0L);
                } else {
                    billStatVO.setWaterMeterPayTotal(waterMeterPayTotal);
                }
            } else {
                billStatVO.setWaterMeterPayTotal(0L);
            }
            if (waterIcSuiteIdList.size() > 0) {
                Long waterIcPayTotal = billWaterDAO.statBill(waterIcSuiteIdList, statDay, 1);
                if (waterIcPayTotal == null) {
                    billStatVO.setWaterICPayTotal(0L);
                } else {
                    billStatVO.setWaterICPayTotal(waterIcPayTotal);
                }
            } else {
                billStatVO.setWaterICPayTotal(0L);
            }
            billStatVO.setWaterPayTotal(billStatVO.getWaterICPayTotal() + billStatVO.getWaterMeterPayTotal());

            Long dichanDiscountWater = billWaterDAO.statDichanDiscount(suiteIdList, statDay);
            Long selfDiscountWater = billWaterDAO.statSelfDiscount(suiteIdList, statDay);
            if (dichanDiscountWater != null) {
                dichanTotal += dichanDiscountWater;
            }
            if (selfDiscountWater != null) {
                selfTotal += selfDiscountWater;
            }
            if (elecIcSuiteIdList.size() > 0) {
                Long elecIc = billElecDAO.statBill(elecIcSuiteIdList, statDay, 1);
                if (elecIc == null) {
                    billStatVO.setElecICPayTotal(0L);
                } else {
                    billStatVO.setElecICPayTotal(elecIc);
                }
            } else {
                billStatVO.setElecICPayTotal(0L);
            }

            if (elecMeterSuiteIdList.size() > 0) {
                Long elecMeter = billElecDAO.statBill(elecMeterSuiteIdList, statDay, 1);
                if (elecMeter == null) {
                    billStatVO.setElecMeterPayTotal(0L);
                } else {
                    billStatVO.setElecMeterPayTotal(elecMeter);
                }
            } else {
                billStatVO.setElecMeterPayTotal(0L);
            }
            billStatVO.setElecPayTotal(billStatVO.getElecICPayTotal() + billStatVO.getElecMeterPayTotal());

            Long dichanDiscountElec = billElecDAO.statDichanDiscount(suiteIdList, statDay);
            Long selfDiscountElec = billElecDAO.statSelfDiscount(suiteIdList, statDay);
            if (dichanDiscountElec != null) {
                dichanTotal += dichanDiscountElec;
            }
            if (selfDiscountElec != null) {
                selfTotal += selfDiscountElec;
            }
            Long depositPayTotal = billExtDAO.statBill(suiteIdList, statDay, 1, depositVarIdList);
            if (depositPayTotal == null) {
                billStatVO.setDepositPayTotal(0L);
            } else {
                billStatVO.setDepositPayTotal(depositPayTotal);
            }

            Iterator<Map.Entry<String, List<Long>>> iterator = extVarMap.entrySet().iterator();
            List<StatObj> statObjs = new ArrayList<StatObj>();
            while (iterator.hasNext()) {
                Map.Entry<String, List<Long>> next = iterator.next();
                StatObj statObj = new StatObj();
                Long extPayTotal = billExtDAO.statBill(suiteIdList, statDay, 1, next.getValue());
                statObj.setName(next.getKey());
                if (extPayTotal == null) {
                    statObj.setFeeTotal(0L);
                } else {
                    statObj.setFeeTotal(extPayTotal);
                }
                statObjs.add(statObj);
            }
            billStatVO.setStatObjList(statObjs);
            List<StatObj> extraList = new ArrayList<StatObj>();
            for (SysVarDO sysVarDO : extraSysVarDOs) {
                StatObj statObj = new StatObj();
                Long aLong = extraFeeDAO.statBill(suiteIdList, statDay, sysVarDO.getVarId());
                statObj.setName(sysVarDO.getVarValue());
                if (aLong == null) {
                    statObj.setFeeTotal(0L);
                } else {
                    statObj.setFeeTotal(aLong);
                }
                extraList.add(statObj);
            }
            billStatVO.setExtraObjList(extraList);
            billStatVO.setEstatePayTotal(estatePayTotal);


            if (billStatVO.getElecPayTotal() == null) {
                billStatVO.setDepositPayTotal(0L);
            }
            if (estatePayTotal == null) {
                billStatVO.setEstatePayTotal(0L);
            }


            Long dichanDiscountExt = billExtDAO.statDichanDiscount(suiteIdList, statDay);
            Long selfDiscountExt = billExtDAO.statSelfDiscount(suiteIdList, statDay);
            if (dichanDiscountExt != null) {
                dichanTotal += dichanDiscountExt;
            }
            if (selfDiscountExt != null) {
                selfTotal += selfDiscountExt;
            }
        }
        if (parkingIdList == null || parkingIdList.size() == 0) {
            billStatVO.setParkingPayTotal(0L);
        } else {
            Long parkingPayTotal = billParkingDAO.statBill(parkingIdList, statDay, 1);
            billStatVO.setParkingPayTotal(parkingPayTotal);
            if (parkingPayTotal == null) {
                billStatVO.setParkingPayTotal(0L);
            }
            Long dichanDiscountExt = billParkingDAO.statDichanDiscount(parkingIdList, statDay);
            Long selfDiscountExt = billParkingDAO.statSelfDiscount(parkingIdList, statDay);
            if (dichanDiscountExt != null) {
                dichanTotal += dichanDiscountExt;
            }
            if (selfDiscountExt != null) {
                selfTotal += selfDiscountExt;
            }
        }
        billStatVO.setSelfDiscount(selfTotal);
        billStatVO.setDichanDiscount(dichanTotal);
        return billStatVO;
    }

    private String getRate(Long a, Long b) {
        if (a == null || b == null) {
            return null;
        }
        if (b.longValue() == 0) {
            return "100%";
        }
        BigDecimal divide = new BigDecimal(a).divide(new BigDecimal(b), 4, RoundingMode.UP);
        NumberFormat fmt = NumberFormat.getPercentInstance();
        fmt.setMaximumFractionDigits(2);
        return fmt.format(divide.doubleValue());
    }


}
